mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-10 14:11:58 +00:00
Compare commits
471 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4c9282790a | ||
|
39a74e42b6 | ||
|
a298c0dcb9 | ||
|
9ee56a5d08 | ||
|
6b80a2c39c | ||
|
f6569edde1 | ||
|
5ab9aa8cf2 | ||
|
8a171d09b5 | ||
|
3e423a1543 | ||
|
6351782c1d | ||
|
4c92868efb | ||
|
2cca9ea11b | ||
|
e12001e4d1 | ||
|
a57607f728 | ||
|
a79af2cac0 | ||
|
be807c5b19 | ||
|
ae03e7076e | ||
|
26e394c398 | ||
|
200aa95784 | ||
|
4eeabb3dbd | ||
|
227bbe4fd8 | ||
|
1461a04a3d | ||
|
52008dc139 | ||
|
f2a10052e4 | ||
|
add64e0cb6 | ||
|
14511e2621 | ||
|
42e0c93121 | ||
|
715bc273ee | ||
|
812541870e | ||
|
9aa5051826 | ||
|
54580b4aeb | ||
|
2b1b6091a3 | ||
|
74a147ab3f | ||
|
07f0595f5a | ||
|
e3422ea6a5 | ||
|
f4103c242f | ||
|
34fb5e9dd9 | ||
|
f6cf0670c1 | ||
|
c7bd036030 | ||
|
b20c573040 | ||
|
6568885c10 | ||
|
31237135c5 | ||
|
d528ed1e97 | ||
|
bb207340fd | ||
|
314e1aeb64 | ||
|
9846f7b04f | ||
|
6e442e93b8 | ||
|
fb3c57aab4 | ||
|
093b3281fb | ||
|
3b027c6c36 | ||
|
f193309e4c | ||
|
7668849a59 | ||
|
1350e68c29 | ||
|
ea63cf76e5 | ||
|
674fa8d7e0 | ||
|
60a31112ea | ||
|
67d8807529 | ||
|
dda1fd6ea3 | ||
|
7a937f1e51 | ||
|
187e9138da | ||
|
b8c9605ae6 | ||
|
8a1d8dba94 | ||
|
b2c87aa22d | ||
|
3748482f51 | ||
|
1f558e4c58 | ||
|
a7d31b9811 | ||
|
42cc7f16c2 | ||
|
c0ca7cc27f | ||
|
27962726b4 | ||
|
aeebd3dcc6 | ||
|
dde8dc90e6 | ||
|
aa1ec3cf35 | ||
|
30ce0a1f01 | ||
|
291684f3d8 | ||
|
0fed714674 | ||
|
f2752929ce | ||
|
cf66b63817 | ||
|
e387ae39cc | ||
|
e3483507d0 | ||
|
55c6eacf95 | ||
|
2ff97bfe83 | ||
|
88874ef191 | ||
|
74af4484da | ||
|
c24812dc20 | ||
|
0e78b61f4c | ||
|
97353e1ee9 | ||
|
024ad00229 | ||
|
c2da1838da | ||
|
93d4e603ed | ||
|
4197d9d5c7 | ||
|
a323e56a5a | ||
|
6f2100e072 | ||
|
a2dcb0ebd7 | ||
|
ef2019d844 | ||
|
a5adc32d79 | ||
|
a5f8e80bcc | ||
|
de3dfc1265 | ||
|
487dc56e3c | ||
|
fd4e630f0f | ||
|
008b33efbd | ||
|
f3e0c43f3b | ||
|
9f6ef99ef5 | ||
|
5e9d7f39d3 | ||
|
0f6950a72e | ||
|
87bba8e381 | ||
|
837fb0cccd | ||
|
0b511e0b55 | ||
|
67aa6ac5fc | ||
|
6805ce85c8 | ||
|
b00e11cb6f | ||
|
3d9b58ea76 | ||
|
02254b2ac4 | ||
|
7df8281358 | ||
|
3f2a143343 | ||
|
c8bfc18f83 | ||
|
8b3bd59d73 | ||
|
a6e915371f | ||
|
f5f1106506 | ||
|
5b0c31154e | ||
|
70a90c3870 | ||
|
a10ab896df | ||
|
5bc0c3975b | ||
|
6e20330424 | ||
|
1c1c9704a1 | ||
|
b7642b5813 | ||
|
69583721da | ||
|
d17c11b8ad | ||
|
57daaa24da | ||
|
da96fd52ca | ||
|
0fd088fc59 | ||
|
dea78f5d30 | ||
|
aa02febb3f | ||
|
84e1c90745 | ||
|
7ce2349edc | ||
|
6d02269164 | ||
|
ba323979ff | ||
|
b1cf324289 | ||
|
acb34b7861 | ||
|
ab1cce1fec | ||
|
7550799a26 | ||
|
6238485d2b | ||
|
8059ccad53 | ||
|
3896979b6c | ||
|
98a978a4d1 | ||
|
cb333d1c20 | ||
|
ee1d33cb41 | ||
|
1e16f74292 | ||
|
8d72d662a0 | ||
|
f346992500 | ||
|
5399fed53b | ||
|
1766ac749d | ||
|
5b31b22840 | ||
|
b4c18c9902 | ||
|
7491ba5156 | ||
|
57d8f4bab7 | ||
|
6c0b29ec3d | ||
|
91adfe22d7 | ||
|
40036caae4 | ||
|
5a0aadb425 | ||
|
d4a8ef2442 | ||
|
5555ee6871 | ||
|
1ba62b2a4c | ||
|
8abf1c3d36 | ||
|
22b6131f93 | ||
|
8a731dce40 | ||
|
a18861a4f6 | ||
|
87f31c5a3a | ||
|
ef878fe20f | ||
|
168aae1a3d | ||
|
ed706aa5d3 | ||
|
fe5a1d8436 | ||
|
54d122ccc1 | ||
|
945fe52df9 | ||
|
f1d9203430 | ||
|
1dc0720582 | ||
|
8dcc19cc63 | ||
|
d4883af0d0 | ||
|
4cb220de66 | ||
|
97bcd725ee | ||
|
38259f9b39 | ||
|
9b1f0d78a5 | ||
|
95d7dbc5fc | ||
|
920366d287 | ||
|
14e26c46fc | ||
|
c934f556cd | ||
|
73901303c5 | ||
|
bbb22a79eb | ||
|
099b072a47 | ||
|
0bf3c078cf | ||
|
9b45f75b48 | ||
|
52914459ea | ||
|
446b08aa03 | ||
|
08fbc569fe | ||
|
a8f50416a3 | ||
|
c5122ddca0 | ||
|
1d93bcbb0d | ||
|
c34f9af62d | ||
|
112875fbfd | ||
|
2d21456342 | ||
|
0363cab870 | ||
|
1f708ad712 | ||
|
475894525d | ||
|
58bad96724 | ||
|
02486a432a | ||
|
6de21cca78 | ||
|
185f7ebeb6 | ||
|
1b55aa9691 | ||
|
51aa490439 | ||
|
4cf2e76430 | ||
|
9e34ae3df8 | ||
|
6a4f82deae | ||
|
0e3173a573 | ||
|
2744561346 | ||
|
9b8ae96c2e | ||
|
adb8913b56 | ||
|
02237bd280 | ||
|
78001ed22c | ||
|
a568aeda17 | ||
|
f890e9f995 | ||
|
0ddeac79bb | ||
|
67ca73820b | ||
|
1df8702e16 | ||
|
12c4481ac2 | ||
|
0f572ec21a | ||
|
9c121743d9 | ||
|
c754eaeb93 | ||
|
1f3e08f439 | ||
|
5efa236cfe | ||
|
df658371cd | ||
|
65f6d0ee45 | ||
|
275c42014e | ||
|
b9e76970f9 | ||
|
d0135e4b76 | ||
|
d405be6273 | ||
|
b7862932e6 | ||
|
970bca464f | ||
|
f76d43eced | ||
|
e07c452cf0 | ||
|
64899ca358 | ||
|
de498664b6 | ||
|
46031feb52 | ||
|
a93686acd5 | ||
|
0a46ec0ab2 | ||
|
aa86d07738 | ||
|
553a8aae1c | ||
|
f1bf73c269 | ||
|
ce39a66934 | ||
|
64fa671f33 | ||
|
70c1da0213 | ||
|
283fffef00 | ||
|
e99e3d69ba | ||
|
f826b08b2b | ||
|
3bd57adeef | ||
|
a4f8b8d4b9 | ||
|
6363c9e17a | ||
|
b8a94ff310 | ||
|
fd9e279715 | ||
|
6210ca95f9 | ||
|
7edba79f69 | ||
|
1eb24d2d85 | ||
|
3305eb91e5 | ||
|
0994545c65 | ||
|
94377f1e30 | ||
|
9c9d3dbbd5 | ||
|
7b4c210773 | ||
|
06d500311c | ||
|
8d95ffc9ff | ||
|
6e05d5d157 | ||
|
d098508e53 | ||
|
dfff72849d | ||
|
d60172e860 | ||
|
3cac4e8206 | ||
|
b35a64d14f | ||
|
738a77301a | ||
|
be0ea5b247 | ||
|
d33dc8e1d4 | ||
|
d72b8c411a | ||
|
10e78191dd | ||
|
6290c46d62 | ||
|
8a61badabc | ||
|
f9946827c4 | ||
|
b812c7856e | ||
|
a3f6e13a7c | ||
|
afffc7e870 | ||
|
fe5a01e2bd | ||
|
03625565e9 | ||
|
8d1d2b4f1b | ||
|
1342c6a7bb | ||
|
17152b69fc | ||
|
1a7027327e | ||
|
7921969222 | ||
|
9cc93de7b2 | ||
|
55c9cf3407 | ||
|
120f45ba92 | ||
|
eacdbd3770 | ||
|
01c347673d | ||
|
93d4701d80 | ||
|
64baf03818 | ||
|
e39606aec5 | ||
|
7581e07c3c | ||
|
a01d375e6f | ||
|
a98f44803a | ||
|
cabc38b386 | ||
|
9ed29967b7 | ||
|
b63a3eae9b | ||
|
1ce46c2039 | ||
|
278aa59302 | ||
|
51a51ecd6b | ||
|
dcc6f23548 | ||
|
10f4b10ae8 | ||
|
24575c436e | ||
|
25c4b677de | ||
|
6f13f36c5a | ||
|
db8b353fb1 | ||
|
2ccdee122a | ||
|
14c1b91a9b | ||
|
5b562edad1 | ||
|
19e577383a | ||
|
115997d367 | ||
|
de2effcefb | ||
|
79b78448e0 | ||
|
05c4f2282e | ||
|
228944c59c | ||
|
ec279bcd5d | ||
|
97770fd831 | ||
|
22c94284ec | ||
|
1a99c54074 | ||
|
b30b7bd252 | ||
|
7ce9183360 | ||
|
06af664a16 | ||
|
7adf58d35f | ||
|
08e42ed877 | ||
|
aa2fb35b41 | ||
|
ab1e762a65 | ||
|
c6201fa2fa | ||
|
0ab31fcc93 | ||
|
7616781ce9 | ||
|
a7c83b9acc | ||
|
a09649c40a | ||
|
0bb0e5b5b0 | ||
|
9f1956b632 | ||
|
0f1ef341f6 | ||
|
48e4d8a5a6 | ||
|
22bd945003 | ||
|
12b986373e | ||
|
fbc5b738ab | ||
|
92c1b2fb9d | ||
|
ca3a7663a0 | ||
|
ae88784bdb | ||
|
4f03115b69 | ||
|
8fc2da1ce9 | ||
|
5f0c65b551 | ||
|
b3f5cf9f76 | ||
|
cb3934eb96 | ||
|
df00db7cb7 | ||
|
af4e0c0a01 | ||
|
b6a56cb0f8 | ||
|
aac9be6887 | ||
|
c831a5e23d | ||
|
0e9633fa5b | ||
|
971f8c9b46 | ||
|
cb89ed65fb | ||
|
34357a83d8 | ||
|
b29afa2248 | ||
|
c89871c4fa | ||
|
2a07b65e25 | ||
|
36286e76e9 | ||
|
267a776620 | ||
|
5da314f03a | ||
|
02b43f42ef | ||
|
1bcde87d42 | ||
|
740bce8c80 | ||
|
801b526b4a | ||
|
fde025ad88 | ||
|
c06b210056 | ||
|
f4a89937ef | ||
|
fc8c37b1e2 | ||
|
fcc4bc9ac4 | ||
|
8ee8be1696 | ||
|
3aeb049d6b | ||
|
2311665003 | ||
|
90fad5d4e8 | ||
|
dee3674494 | ||
|
91b91e3dee | ||
|
c085d42531 | ||
|
d0323836ad | ||
|
628d299980 | ||
|
b532ba9d54 | ||
|
195f5b1a8c | ||
|
c8718ca722 | ||
|
9a48b09f32 | ||
|
3421bcb532 | ||
|
e3175e9a98 | ||
|
f5c71e6098 | ||
|
725ef34ccb | ||
|
b7224b3d20 | ||
|
24c6abedb5 | ||
|
bf2f123aa7 | ||
|
0e90fe9710 | ||
|
638058629d | ||
|
0e7660be83 | ||
|
35b4ad5dbe | ||
|
ba61253c94 | ||
|
90b91b87ef | ||
|
bfce7cf3ad | ||
|
03a261c4c5 | ||
|
4b3558ff12 | ||
|
4355add778 | ||
|
92fbaf29d4 | ||
|
8e15dba3eb | ||
|
2206479e06 | ||
|
abeaff52e8 | ||
|
76be8d2bec | ||
|
ce27304eae | ||
|
060cf3aa3c | ||
|
f1fdf72c5b | ||
|
b580a52459 | ||
|
d13da0cdfa | ||
|
ca236d9814 | ||
|
bf5032675f | ||
|
8398a5dca0 | ||
|
52731727c6 | ||
|
2f45231149 | ||
|
447d0c4f56 | ||
|
5e920054f4 | ||
|
2f66f068a6 | ||
|
2461b75f61 | ||
|
96231517bd | ||
|
b73b8df892 | ||
|
08e49c98dd | ||
|
ba50617181 | ||
|
0d621badd7 | ||
|
661ddce806 | ||
|
aa8b0256e1 | ||
|
8990581cc1 | ||
|
04d76a182a | ||
|
27fbf633df | ||
|
358ca8dc9e | ||
|
9a25862cc9 | ||
|
ac7e58ddc5 | ||
|
6bcaa1be04 | ||
|
a1bf0f5480 | ||
|
2c3d5dd297 | ||
|
6b32d96f08 | ||
|
69dd388133 | ||
|
29106d307f | ||
|
ef8b3578df | ||
|
dc5128b447 | ||
|
741ac97c3b | ||
|
3f5cb68250 | ||
|
fdb4f9e338 | ||
|
f3f3a1db4b | ||
|
eb922e1c95 | ||
|
46da34fabd | ||
|
7dee8314fb | ||
|
f888f8244e | ||
|
8e3eeb9dd7 | ||
|
012d2f37c7 | ||
|
f5f73162bd | ||
|
e7a83f2641 | ||
|
2a300f9b7c | ||
|
ac0ed124aa | ||
|
cee2da9700 | ||
|
2bc914b649 | ||
|
89dd6f7b35 | ||
|
c82e8d652a | ||
|
a9a911e77f | ||
|
e59bb3261c | ||
|
d999558b33 | ||
|
897bfa8410 | ||
|
cce8ef50ef |
436
.github/workflows/ci.yml
vendored
436
.github/workflows/ci.yml
vendored
File diff suppressed because it is too large
Load Diff
16
.github/workflows/master_release.yml
vendored
16
.github/workflows/master_release.yml
vendored
@@ -34,12 +34,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.1.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.1.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.1.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.35.2
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v7.1.0
|
||||
with:
|
||||
username: ${{ env.GIT_USERNAME }}
|
||||
email: ${{ env.GIT_EMAIL }}
|
||||
@@ -63,12 +63,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v1.35.2
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v1.35.2
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v1.35.2
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.1.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.1.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.1.0
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.35.2
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v7.1.0
|
||||
with:
|
||||
username: ${{ env.GIT_USERNAME }}
|
||||
email: ${{ env.GIT_EMAIL }}
|
||||
|
14
.pre-commit-config.yaml
Normal file
14
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
repos:
|
||||
- repo: https://github.com/Yelp/detect-secrets
|
||||
rev: v1.5.0
|
||||
hooks:
|
||||
- id: detect-secrets
|
||||
args: ["--baseline", ".secrets.baseline"]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: check-format-and-headers
|
||||
name: Check format and headers and fix if necessary
|
||||
entry: ./scripts/hooks/check-format-and-headers.sh
|
||||
language: script
|
||||
files: ".*.java"
|
||||
pass_filenames: false
|
1892
.secrets.baseline
Normal file
1892
.secrets.baseline
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,52 @@ Thanks for your interest in contributing to this project!
|
||||
|
||||
The following is a set of guidelines for contributing to this library. Most of them will make the life of the reviewer easier and therefore decrease the time required for the patch be included in the next version.
|
||||
|
||||
The project uses [pre-commit](https://pre-commit.com/) to format code (with [Spotless](https://github.com/diffplug/spotless)), validate license headers and check for secrets (with [detect-secrets](https://github.com/Yelp/detect-secrets)). To install the pre-commit hooks then first install pre-commit and then run:
|
||||
```shell
|
||||
pre-commit install
|
||||
```
|
||||
When you make a commit then these hooks will run and check the modified files. If it makes changes then you can review them and then `git commit` again to accept the changes.
|
||||
|
||||
#### Code Quality
|
||||
This project uses `spotless` that enforces `alfresco-formatter.xml` to ensure code quality.
|
||||
|
||||
To check code-style violations you can use:
|
||||
```bash
|
||||
mvn spotless:check
|
||||
```
|
||||
To reformat files you can use:
|
||||
```bash
|
||||
mvn spotless:apply
|
||||
```
|
||||
|
||||
#### Secret Detection
|
||||
|
||||
We are using [detect-secrets](https://github.com/Yelp/detect-secrets) to try to avoid accidentally publishing secret keys.
|
||||
If you have pre-commit installed then this should run automatically when making a commit. Usually there should be no issues,
|
||||
but if it finds a potential issue (e.g. a high entropy string) then you will see the following:
|
||||
|
||||
```shell
|
||||
Detect secrets...........................................................Failed
|
||||
- hook id: detect-secrets
|
||||
- exit code: 1
|
||||
|
||||
ERROR: Potential secrets about to be committed to git repo!
|
||||
|
||||
Secret Type: Secret Keyword
|
||||
Location: test.txt:1
|
||||
```
|
||||
|
||||
If this is a false positive and you actually want to commit the string then run these two commands:
|
||||
|
||||
```shell
|
||||
detect-secrets scan --baseline .secrets.baseline
|
||||
detect-secrets audit .secrets.baseline
|
||||
```
|
||||
|
||||
This will update the baseline file to include your new code and then allow you to review the detected secret and mark it as a false positive.
|
||||
Once you are finished then you can add `.secrets.baseline` to the staged changes and you should be able to create a commit.
|
||||
|
||||
|
||||
Because this project forms a part of Alfresco Content Services, the guidelines are hosted in the [Alfresco Social Community](https://hub.alfresco.com/t5/alfresco-content-services-ecm/ct-p/ECM-software) where they can be referenced from multiple projects.
|
||||
|
||||
You can report an issue in the ALF project of the [Alfresco issue tracker](http://issues.alfresco.com).
|
||||
|
75
README.md
75
README.md
@@ -2,38 +2,57 @@
|
||||
|
||||
[](https://github.com/Alfresco/alfresco-community-repo/actions/workflows/master_release.yml)
|
||||
|
||||
#### Alfresco Core
|
||||
## Table of Contents
|
||||
1. [Content](#content)
|
||||
2. [Artifacts](#artifacts)
|
||||
3. [Setup](#setting-up-and-building-your-development-environment)
|
||||
4. [Branches](#branches)
|
||||
5. [Contributing](#contributing-guide)
|
||||
6. [Helpful links](#helpful-links)
|
||||
|
||||
|
||||
## Content
|
||||
Alfresco Community Repository contains following libraries:
|
||||
|
||||
### Alfresco Core
|
||||
Core is a library packaged as a jar file which contains the following:
|
||||
|
||||
Alfresco Core is a library packaged as a jar file which contains the following:
|
||||
* Various helpers and utils
|
||||
* Canned queries interface and supporting classes
|
||||
* Generic encryption supporting classes
|
||||
|
||||
#### Alfresco Data Model
|
||||
Data model is a library packaged as a jar file which contains the following:
|
||||
### Alfresco Data Model
|
||||
|
||||
Data Model is a library packaged as a jar file which contains the following:
|
||||
|
||||
* Dictionary, Repository and Search Services interfaces
|
||||
* Models for data types and Dictionary implementation
|
||||
* Parsers
|
||||
|
||||
#### Alfresco Repository
|
||||
### Alfresco Repository
|
||||
|
||||
Repository is a library packaged as a jar file which contains the following:
|
||||
|
||||
* DAOs and SQL scripts
|
||||
* Various Service implementations
|
||||
* Utility classes
|
||||
|
||||
#### Alfresco Remote API
|
||||
### Alfresco Remote API
|
||||
|
||||
Remote API is a library packaged as a jar file which contains the following:
|
||||
|
||||
* REST API framework
|
||||
* WebScript implementations including [V1 REST APIs](https://hub.alfresco.com/t5/alfresco-content-services-blog/v1-rest-api-10-things-you-should-know/ba-p/287692)
|
||||
* [OpenCMIS](https://chemistry.apache.org/java/opencmis.html) implementations
|
||||
|
||||
#### Artifacts
|
||||
## Artifacts
|
||||
|
||||
The artifacts can be obtained by:
|
||||
* downloading from [Alfresco maven repository](https://artifacts.alfresco.com/nexus/content/groups/public)
|
||||
* downloading from [Alfresco maven repository](https://artifacts.alfresco.com/nexus/#browse/browse:public)
|
||||
* as Maven dependency by adding the dependency to your pom file:
|
||||
~~~
|
||||
|
||||
~~~xml
|
||||
|
||||
<dependency>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-core</artifactId>
|
||||
@@ -64,34 +83,46 @@ The artifacts can be obtained by:
|
||||
<version>version</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
|
||||
~~~
|
||||
|
||||
and Alfresco maven repository:
|
||||
~~~
|
||||
|
||||
~~~xml
|
||||
|
||||
<repository>
|
||||
<id>alfresco-maven-repo</id>
|
||||
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
|
||||
</repository>
|
||||
|
||||
~~~
|
||||
|
||||
The SNAPSHOT versions of the artifact are not published.
|
||||
|
||||
## Setting up and building your development environment
|
||||
See the [Development Tomcat Environment](https://github.com/Alfresco/acs-community-packaging/tree/master/dev/README.md)
|
||||
page which will show you how to try out your repository changes in a local tomcat instance.
|
||||
If you wish to use Docker images, take a look at the aliases ending in `D` and the docker-compose files in this
|
||||
project's test modules.
|
||||
|
||||
See the [**Development Tomcat Environment**](https://github.com/Alfresco/acs-community-packaging/tree/master/dev/README.md)
|
||||
page which will show you how to try out your repository changes in a local Tomcat instance or using Docker containers.
|
||||
|
||||
## Branches
|
||||
This project has a branch for each ACS release. For example the code in ACS 6.2.1 is a
|
||||
branch called `releases/6.2.2`. In addition to the original 6.2.2 release it will also contain Hot Fixes
|
||||
added later. The latest unreleased code is on the `master` branch. There are also `.N` branches, such as
|
||||
`releases/7.1.N` on which we gather unreleased fixes for future service pack releases. They do not indicate
|
||||
|
||||
This project has a branch for each ACS release. For example the code in ACS 6.2.2 is a
|
||||
branch called **`release/6.2.2`**. In addition to the original 6.2.2 release it will also contain Hot Fixes
|
||||
added later. The latest unreleased code is on the **`master`** branch. There are also **`.N`** branches, such as
|
||||
**`release/7.1.N`** on which we gather unreleased fixes for future service pack releases. They do not indicate
|
||||
that one is planned.
|
||||
|
||||
For historic reasons the version of artifacts created on each branch do not match the ACS version.
|
||||
For example artifact in ACS 7.2.0 will be `14.<something>`.
|
||||
For example artifact in ACS 7.2.0 will be **`14.<something>`**.
|
||||
|
||||
The enterprise projects which extend the `alfresco-community-repo` use the same branch names and leading
|
||||
The enterprise projects which extend the **`alfresco-community-repo`** use the same branch names and leading
|
||||
artifact version number.
|
||||
|
||||
### Contributing guide
|
||||
Please use [this guide](CONTRIBUTING.md) to make a contribution to the project.
|
||||
## Contributing guide
|
||||
|
||||
Please use [**this guide**](CONTRIBUTING.md) to make a contribution to the project.
|
||||
|
||||
## Helpful links
|
||||
|
||||
- [Alfresco Content Services Documentation](https://docs.alfresco.com/content-services/latest/)
|
||||
- [Alfresco Platform](https://www.hyland.com/en/products/alfresco-platform)
|
||||
|
401
alfresco-formatter.xml
Normal file
401
alfresco-formatter.xml
Normal file
@@ -0,0 +1,401 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="23">
|
||||
<profile kind="CodeFormatterProfile" name="Spotless" version="23">
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="999"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_if_empty"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="999"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
@@ -84,6 +84,12 @@
|
||||
<artifactId>okhttp</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>${dependency.awaitility.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
@@ -92,7 +98,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.docker-java</groupId>
|
||||
<artifactId>docker-java</artifactId>
|
||||
<version>3.3.2</version>
|
||||
<version>3.4.0</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
|
@@ -49,6 +49,7 @@ import org.alfresco.rest.rm.community.requests.gscore.api.TransferAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.TransferContainerAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledRecordFolderAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RetentionScheduleAPI;
|
||||
import org.alfresco.utility.data.DataUserAIS;
|
||||
import org.alfresco.utility.model.RepoTestModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
@@ -254,4 +255,14 @@ public class RestAPIFactory
|
||||
{
|
||||
return getGSCoreAPI(userModel).usingHoldsAPI();
|
||||
}
|
||||
|
||||
public RetentionScheduleAPI getRetentionScheduleAPI()
|
||||
{
|
||||
return getGSCoreAPI(null).usingRetentionScheduleAPI();
|
||||
}
|
||||
|
||||
public RetentionScheduleAPI getRetentionScheduleAPI(UserModel userModel)
|
||||
{
|
||||
return getGSCoreAPI(userModel).usingRetentionScheduleAPI();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,41 @@
|
||||
/*-
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.hold;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BulkBodyCancel
|
||||
{
|
||||
private String reason;
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.hold;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.alfresco.rest.search.RestRequestQueryModel;
|
||||
import org.alfresco.utility.model.TestModel;
|
||||
|
||||
/**
|
||||
* POJO for hold bulk request
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HoldBulkOperation extends TestModel
|
||||
{
|
||||
public enum HoldBulkOperationType
|
||||
{
|
||||
ADD
|
||||
}
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private RestRequestQueryModel query;
|
||||
@JsonProperty(required = true)
|
||||
private HoldBulkOperationType op;
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.hold;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* POJO for hold bulk request entry
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HoldBulkOperationEntry
|
||||
{
|
||||
private String bulkStatusId;
|
||||
|
||||
private long totalItems;
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.hold;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.alfresco.utility.model.TestModel;
|
||||
|
||||
/**
|
||||
* POJO for hold bulk request
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HoldBulkStatus extends TestModel
|
||||
{
|
||||
private String bulkStatusId;
|
||||
|
||||
private String startTime;
|
||||
|
||||
private String endTime;
|
||||
|
||||
private long processedItems;
|
||||
|
||||
private long errorsCount;
|
||||
|
||||
private long totalItems;
|
||||
|
||||
private String lastError;
|
||||
|
||||
private String status;
|
||||
|
||||
private boolean isCancelled;
|
||||
|
||||
private String cancellationReason;
|
||||
|
||||
private HoldBulkOperation holdBulkOperation;
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.hold;
|
||||
|
||||
import org.alfresco.rest.core.RestModels;
|
||||
|
||||
/**
|
||||
* Handle collection of {@link HoldBulkStatusEntry}
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
public class HoldBulkStatusCollection extends RestModels<HoldBulkStatusEntry, HoldBulkStatusCollection>
|
||||
{
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.hold;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.alfresco.rest.core.RestModels;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HoldBulkStatusEntry extends RestModels<HoldBulkStatus, HoldBulkStatusEntry>
|
||||
{
|
||||
private HoldBulkStatus entry;
|
||||
}
|
@@ -48,5 +48,5 @@ import org.alfresco.rest.core.RestModels;
|
||||
public class HoldChildEntry extends RestModels<Hold, HoldChildEntry>
|
||||
{
|
||||
@JsonProperty
|
||||
private HoldChildEntry entry;
|
||||
private HoldChild entry;
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.retentionschedule;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.alfresco.utility.model.TestModel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* retention schedule
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class RetentionSchedule extends TestModel
|
||||
{
|
||||
private String id ;
|
||||
private String parentId;
|
||||
private String authority;
|
||||
private String instructions;
|
||||
private boolean isRecordLevel;
|
||||
private boolean isUnpublishedUpdates;
|
||||
private List<RetentionScheduleActionDefinition> actions;
|
||||
|
||||
public boolean getIsRecordLevel()
|
||||
{
|
||||
return isRecordLevel;
|
||||
}
|
||||
|
||||
public void setIsRecordLevel(boolean recordLevel) {
|
||||
isRecordLevel = recordLevel;
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.retentionschedule;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* retention schedule action definition
|
||||
*/
|
||||
@Data
|
||||
public class RetentionScheduleActionDefinition
|
||||
{
|
||||
private String id;
|
||||
private String name;
|
||||
private int periodAmount;
|
||||
private String period;
|
||||
private String periodProperty;
|
||||
private boolean combineRetentionStepConditions;
|
||||
private List<String> events;
|
||||
private boolean eligibleOnFirstCompleteEvent;
|
||||
private String description;
|
||||
private boolean retainRecordMetadataAfterDestruction;
|
||||
private String location;
|
||||
private int index;
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.retentionschedule;
|
||||
|
||||
import org.alfresco.rest.core.RestModels;
|
||||
public class RetentionScheduleCollection extends RestModels<RetentionScheduleEntry, RetentionScheduleCollection>
|
||||
{
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.retentionschedule;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import org.alfresco.rest.core.RestModels;
|
||||
@Data
|
||||
public class RetentionScheduleEntry extends RestModels<RetentionSchedule, RetentionScheduleEntry>
|
||||
{
|
||||
@JsonProperty
|
||||
private RetentionSchedule entry;
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.retentionschedule;
|
||||
|
||||
import org.alfresco.rest.core.RestModels;
|
||||
|
||||
public class RetentionScheduleStepCollection extends RestModels<RetentionScheduleStepEntry, RetentionScheduleStepCollection>
|
||||
{
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.model.retentionschedule;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import org.alfresco.rest.core.RestModels;
|
||||
|
||||
@Data
|
||||
public class RetentionScheduleStepEntry extends RestModels<RetentionScheduleActionDefinition, RetentionScheduleStepEntry>
|
||||
{
|
||||
@JsonProperty
|
||||
private RetentionScheduleActionDefinition entry;
|
||||
}
|
@@ -47,6 +47,7 @@ import org.alfresco.rest.rm.community.requests.gscore.api.TransferAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.TransferContainerAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledContainerAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.UnfiledRecordFolderAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RetentionScheduleAPI;
|
||||
|
||||
/**
|
||||
* Defines the entire GS Core API
|
||||
@@ -193,4 +194,9 @@ public class GSCoreAPI extends RMModelRequest
|
||||
}
|
||||
|
||||
public HoldsAPI usingHoldsAPI() { return new HoldsAPI(getRmRestWrapper()); }
|
||||
|
||||
public RetentionScheduleAPI usingRetentionScheduleAPI()
|
||||
{
|
||||
return new RetentionScheduleAPI(getRmRestWrapper());
|
||||
}
|
||||
}
|
||||
|
@@ -38,7 +38,12 @@ import static org.springframework.http.HttpMethod.POST;
|
||||
import static org.springframework.http.HttpMethod.PUT;
|
||||
|
||||
import org.alfresco.rest.core.RMRestWrapper;
|
||||
import org.alfresco.rest.rm.community.model.hold.BulkBodyCancel;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkOperation;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkOperationEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkStatus;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkStatusCollection;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChild;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChildCollection;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldDeletionReason;
|
||||
@@ -287,4 +292,155 @@ public class HoldsAPI extends RMModelRequest
|
||||
{
|
||||
deleteHoldChild(holdId, holdChildId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a bulk process for a hold.
|
||||
*
|
||||
* @param holdBulkOperation The bulk operation details
|
||||
* @param hold The identifier of a hold
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The {@link HoldBulkOperationEntry} for the started bulk process
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code hold} or {@code holdBulkOperation} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to start a bulk process for {@code hold}</li>
|
||||
* <li>{@code hold} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public HoldBulkOperationEntry startBulkProcess(HoldBulkOperation holdBulkOperation, String hold, String parameters)
|
||||
{
|
||||
mandatoryObject("holdBulkOperation", holdBulkOperation);
|
||||
mandatoryString("hold", hold);
|
||||
|
||||
return getRmRestWrapper().processModel(HoldBulkOperationEntry.class, requestWithBody(
|
||||
POST,
|
||||
toJson(holdBulkOperation),
|
||||
"holds/{hold}/bulk",
|
||||
hold,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #startBulkProcess(HoldBulkOperation, String, String)}
|
||||
*/
|
||||
public HoldBulkOperationEntry startBulkProcess(HoldBulkOperation holdBulkOperation, String hold)
|
||||
{
|
||||
return startBulkProcess(holdBulkOperation, hold, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of a bulk process for a hold.
|
||||
*
|
||||
* @param holdId The identifier of a hold
|
||||
* @param holdBulkStatusId The identifier of a bulk status operation
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The {@link HoldBulkStatus} for the given {@code holdId} and {@code holdBulkStatusId}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code holdId} or {@code holdBulkStatusId} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to get the bulk status for {@code holdId}</li>
|
||||
* <li>{@code holdId} or {@code holdBulkStatusId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public HoldBulkStatus getBulkStatus(String holdId, String holdBulkStatusId, String parameters)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
mandatoryString("holdBulkStatusId", holdBulkStatusId);
|
||||
|
||||
return getRmRestWrapper().processModel(HoldBulkStatus.class, simpleRequest(
|
||||
GET,
|
||||
"holds/{holdId}/bulk-statuses/{holdBulkStatusId}",
|
||||
holdId,
|
||||
holdBulkStatusId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #getBulkStatus(String, String, String)}
|
||||
*/
|
||||
public HoldBulkStatus getBulkStatus(String holdId, String holdBulkStatusId)
|
||||
{
|
||||
return getBulkStatus(holdId, holdBulkStatusId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the statuses of all bulk processes for a hold.
|
||||
*
|
||||
* @param holdId The identifier of a hold
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The {@link HoldBulkStatusCollection} for the given {@code holdId}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code holdId} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to get the bulk statuses for {@code holdId}</li>
|
||||
* <li>{@code holdId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public HoldBulkStatusCollection getBulkStatuses(String holdId, String parameters)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
|
||||
return getRmRestWrapper().processModels(HoldBulkStatusCollection.class, simpleRequest(
|
||||
GET,
|
||||
"holds/{holdId}/bulk-statuses",
|
||||
holdId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #getBulkStatuses(String, String)}
|
||||
*/
|
||||
public HoldBulkStatusCollection getBulkStatuses(String holdId)
|
||||
{
|
||||
return getBulkStatuses(holdId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a bulk operation for a hold.
|
||||
*
|
||||
* @param holdId The identifier of a hold
|
||||
* @param bulkStatusId The identifier of a bulk status operation
|
||||
* @param bulkBodyCancel The bulk body cancel model
|
||||
* @param parameters The URL parameters to add
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code holdId}, {@code bulkStatusId} or {@code bulkBodyCancel} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to cancel the bulk operation for {@code bulkStatusId}</li>
|
||||
* <li>{@code holdId} or {@code bulkStatusId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void cancelBulkOperation(String holdId, String bulkStatusId, BulkBodyCancel bulkBodyCancel, String parameters)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
mandatoryString("bulkStatusId", bulkStatusId);
|
||||
mandatoryObject("bulkBodyCancel", bulkBodyCancel);
|
||||
|
||||
getRmRestWrapper().processEmptyModel(requestWithBody(
|
||||
POST,
|
||||
toJson(bulkBodyCancel),
|
||||
"holds/{holdId}/bulk-statuses/{bulkStatusId}/cancel",
|
||||
holdId,
|
||||
bulkStatusId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #cancelBulkOperation(String, String, BulkBodyCancel, String)}
|
||||
*/
|
||||
public void cancelBulkOperation(String holdId, String bulkStatusId, BulkBodyCancel bulkBodyCancel)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
mandatoryString("bulkStatusId", bulkStatusId);
|
||||
mandatoryObject("bulkBodyCancel", bulkBodyCancel);
|
||||
|
||||
cancelBulkOperation(holdId, bulkStatusId, bulkBodyCancel, EMPTY);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.requests.gscore.api;
|
||||
|
||||
import org.alfresco.rest.core.RMRestWrapper;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionSchedule;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionScheduleActionDefinition;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionScheduleCollection;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionScheduleStepCollection;
|
||||
import org.alfresco.rest.rm.community.requests.RMModelRequest;
|
||||
|
||||
import static org.alfresco.rest.core.RestRequest.requestWithBody;
|
||||
import static org.alfresco.rest.core.RestRequest.simpleRequest;
|
||||
import static org.alfresco.rest.rm.community.util.ParameterCheck.mandatoryObject;
|
||||
import static org.alfresco.rest.rm.community.util.ParameterCheck.mandatoryString;
|
||||
import static org.alfresco.rest.rm.community.util.PojoUtility.toJson;
|
||||
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||
import static org.springframework.http.HttpMethod.GET;
|
||||
import static org.springframework.http.HttpMethod.POST;
|
||||
|
||||
public class RetentionScheduleAPI extends RMModelRequest
|
||||
{
|
||||
|
||||
/**
|
||||
* @param rmRestWrapper
|
||||
*/
|
||||
public RetentionScheduleAPI(RMRestWrapper rmRestWrapper)
|
||||
{
|
||||
super(rmRestWrapper);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a retention schedule.
|
||||
*
|
||||
* @param retentionScheduleModel The retentionSchedule model
|
||||
* @param recordCategoryId The identifier of a record category
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The created {@link RetentionSchedule}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code recordCategoryId} is not a valid format or {@code recordCategoryId} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to add children to {@code recordCategoryId}</li>
|
||||
* <li>{@code recordCategoryId} does not exist</li>
|
||||
* <li>new name clashes with an existing node in the current parent container</li>
|
||||
* </ul>
|
||||
*/
|
||||
public RetentionSchedule createRetentionSchedule(RetentionSchedule retentionScheduleModel, String recordCategoryId, String parameters)
|
||||
{
|
||||
mandatoryString("recordCategoryId", recordCategoryId);
|
||||
mandatoryObject("retentionScheduleModel", retentionScheduleModel);
|
||||
|
||||
return getRmRestWrapper().processModel(RetentionSchedule.class, requestWithBody(
|
||||
POST,
|
||||
toJson(retentionScheduleModel),
|
||||
"record-categories/{recordCategoryId}/retention-schedules",
|
||||
recordCategoryId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #createRetentionSchedule(RetentionSchedule, String, String)}
|
||||
*/
|
||||
public RetentionSchedule createRetentionSchedule(RetentionSchedule retentionScheduleModel, String recordCategoryId)
|
||||
{
|
||||
return createRetentionSchedule(retentionScheduleModel, recordCategoryId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the retentionSchedule of a record category.
|
||||
*
|
||||
* @param recordCategoryId The identifier of a record category
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The {@link RetentionSchedule} for the given {@code recordCategoryId}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to read {@code recordCategoryId}</li>
|
||||
* <li>{@code recordCategoryId} does not exist</li>
|
||||
*</ul>
|
||||
*/
|
||||
public RetentionScheduleCollection getRetentionSchedule(String recordCategoryId, String parameters)
|
||||
{
|
||||
mandatoryString("recordCategoryId", recordCategoryId);
|
||||
|
||||
return getRmRestWrapper().processModels(RetentionScheduleCollection.class, simpleRequest(
|
||||
GET,
|
||||
"record-categories/{recordCategoryId}/retention-schedules?{parameters}",
|
||||
recordCategoryId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #getRetentionSchedule(String, String)}
|
||||
*/
|
||||
public RetentionScheduleCollection getRetentionSchedule(String recordCategoryId)
|
||||
{
|
||||
return getRetentionSchedule(recordCategoryId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a step in the retention schedule.
|
||||
*
|
||||
* @param retentionScheduleActionDefinition The retentionScheduleActionDefinition model
|
||||
* @param retentionScheduleId The identifier of a retention schedule id
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The created {@link RetentionScheduleActionDefinition}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code retentionScheduleId} is not a valid format or {@code retentionScheduleId} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to add children to {@code retentionScheduleId}</li>
|
||||
* <li>{@code retentionScheduleId} does not exist</li>
|
||||
* <li>new name clashes with an existing node in the current parent container</li>
|
||||
* </ul>
|
||||
*/
|
||||
public RetentionScheduleActionDefinition createRetentionScheduleStep(RetentionScheduleActionDefinition retentionScheduleActionDefinition, String retentionScheduleId, String parameters)
|
||||
{
|
||||
mandatoryString("retentionScheduleId", retentionScheduleId);
|
||||
mandatoryObject("retentionScheduleActionDefinition", retentionScheduleActionDefinition);
|
||||
|
||||
return getRmRestWrapper().processModel(RetentionScheduleActionDefinition.class, requestWithBody(
|
||||
POST,
|
||||
toJson(retentionScheduleActionDefinition),
|
||||
"retention-schedules/{retentionScheduleId}/retention-steps",
|
||||
retentionScheduleId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #createRetentionScheduleStep(RetentionScheduleActionDefinition, String)} (RetentionSchedule, String, String)}
|
||||
*/
|
||||
public RetentionScheduleActionDefinition createRetentionScheduleStep(RetentionScheduleActionDefinition retentionScheduleActionDefinition, String retentionScheduleId)
|
||||
{
|
||||
return createRetentionScheduleStep(retentionScheduleActionDefinition, retentionScheduleId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the retentionSchedule of a record category.
|
||||
*
|
||||
* @param retentionScheduleId The identifier of a record category
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The {@link RetentionScheduleActionDefinition} for the given {@code recordCategoryId}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to read {@code recordCategoryId}</li>
|
||||
* <li>{@code recordCategoryId} does not exist</li>
|
||||
*</ul>
|
||||
*/
|
||||
public RetentionScheduleStepCollection getRetentionScheduleStep(String retentionScheduleId, String parameters)
|
||||
{
|
||||
mandatoryString("retentionScheduleId", retentionScheduleId);
|
||||
|
||||
return getRmRestWrapper().processModels(RetentionScheduleStepCollection.class, simpleRequest(
|
||||
GET,
|
||||
"retention-schedules/{retentionScheduleId}/retention-steps?{parameters}",
|
||||
retentionScheduleId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #getRetentionScheduleStep(String, String)}
|
||||
*/
|
||||
public RetentionScheduleStepCollection getRetentionScheduleStep(String recordCategoryId)
|
||||
{
|
||||
return getRetentionScheduleStep(recordCategoryId, EMPTY);
|
||||
}
|
||||
}
|
@@ -0,0 +1,614 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.hold;
|
||||
|
||||
import static org.alfresco.rest.rm.community.base.TestData.HOLD_DESCRIPTION;
|
||||
import static org.alfresco.rest.rm.community.base.TestData.HOLD_REASON;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_FILING;
|
||||
import static org.alfresco.rest.rm.community.model.user.UserPermissions.PERMISSION_READ_RECORDS;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.http.HttpStatus.ACCEPTED;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.dataprep.ContentActions;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.hold.BulkBodyCancel;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkOperation;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkOperation.HoldBulkOperationType;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkOperationEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkStatus;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkStatusCollection;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldBulkStatusEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChild;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChildEntry;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.search.RestRequestQueryModel;
|
||||
import org.alfresco.rest.search.SearchRequest;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.FolderModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* API tests for adding items to holds via the bulk process
|
||||
*/
|
||||
public class AddToHoldsBulkV1Tests extends BaseRMRestTest
|
||||
{
|
||||
private static final String ACCESS_DENIED_ERROR_MESSAGE = "Access Denied. You do not have the appropriate " +
|
||||
"permissions to perform this operation.";
|
||||
private static final int NUMBER_OF_FILES = 5;
|
||||
private final List<FileModel> addedFiles = new ArrayList<>();
|
||||
private final List<UserModel> users = new ArrayList<>();
|
||||
private final List<Hold> holds = new ArrayList<>();
|
||||
private Hold hold;
|
||||
private Hold hold2;
|
||||
private Hold hold3;
|
||||
private FolderModel rootFolder;
|
||||
private HoldBulkOperation holdBulkOperation;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
@Autowired
|
||||
private ContentActions contentActions;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void preconditionForAddContentToHold()
|
||||
{
|
||||
STEP("Create a hold.");
|
||||
hold = getRestAPIFactory().getFilePlansAPI(getAdminUser()).createHold(
|
||||
Hold.builder().name("HOLD" + generateTestPrefix(AddToHoldsV1Tests.class)).description(HOLD_DESCRIPTION)
|
||||
.reason(HOLD_REASON).build(), FILE_PLAN_ALIAS);
|
||||
holds.add(hold);
|
||||
|
||||
STEP("Create test files.");
|
||||
testSite = dataSite.usingAdmin().createPublicRandomSite();
|
||||
|
||||
rootFolder = dataContent.usingAdmin().usingSite(testSite).createFolder();
|
||||
FolderModel folder1 = dataContent.usingAdmin().usingResource(rootFolder).createFolder();
|
||||
FolderModel folder2 = dataContent.usingAdmin().usingResource(folder1).createFolder();
|
||||
|
||||
// Add files to subfolders in the site
|
||||
for (int i = 0; i < NUMBER_OF_FILES; i++)
|
||||
{
|
||||
FileModel documentHeld = dataContent.usingAdmin()
|
||||
.usingResource(i % 2 == 0 ? folder1 : folder2)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
addedFiles.add(documentHeld);
|
||||
}
|
||||
|
||||
RestRequestQueryModel queryReq = getContentFromSiteQuery(testSite.getId());
|
||||
SearchRequest searchRequest = new SearchRequest();
|
||||
searchRequest.setQuery(queryReq);
|
||||
|
||||
STEP("Wait until all files are searchable.");
|
||||
await().atMost(30, TimeUnit.SECONDS)
|
||||
.until(() -> getRestAPIFactory().getSearchAPI(null).search(searchRequest).getPagination()
|
||||
.getTotalItems() == NUMBER_OF_FILES);
|
||||
|
||||
holdBulkOperation = HoldBulkOperation.builder()
|
||||
.query(queryReq)
|
||||
.op(HoldBulkOperationType.ADD).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* Then the content is added to the hold and the status of the bulk operation is DONE
|
||||
*/
|
||||
@Test
|
||||
public void addContentFromTestSiteToHoldUsingBulkAPI()
|
||||
{
|
||||
UserModel userAddHoldPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole.SiteCollaborator, hold.getId(), UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
|
||||
users.add(userAddHoldPermission);
|
||||
|
||||
STEP("Add content from the site to the hold using the bulk API.");
|
||||
HoldBulkOperationEntry bulkOperationEntry = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.startBulkProcess(holdBulkOperation, hold.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(ACCEPTED);
|
||||
assertEquals(NUMBER_OF_FILES, bulkOperationEntry.getTotalItems());
|
||||
|
||||
STEP("Wait until all files are added to the hold.");
|
||||
await().atMost(20, TimeUnit.SECONDS).until(
|
||||
() -> getRestAPIFactory().getHoldsAPI(getAdminUser()).getChildren(hold.getId()).getEntries().size()
|
||||
== NUMBER_OF_FILES);
|
||||
List<String> holdChildrenNodeRefs = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getChildren(hold.getId()).getEntries().stream().map(HoldChildEntry::getEntry).map(
|
||||
HoldChild::getId).toList();
|
||||
assertEquals(addedFiles.stream().map(FileModel::getNodeRefWithoutVersion).sorted().toList(),
|
||||
holdChildrenNodeRefs.stream().sorted().toList());
|
||||
|
||||
STEP("Check the bulk status.");
|
||||
HoldBulkStatus holdBulkStatus = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getBulkStatus(hold.getId(), bulkOperationEntry.getBulkStatusId());
|
||||
assertBulkProcessStatus(holdBulkStatus, NUMBER_OF_FILES, 0, null, holdBulkOperation);
|
||||
|
||||
STEP("Check the bulk statuses.");
|
||||
HoldBulkStatusCollection holdBulkStatusCollection = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getBulkStatuses(hold.getId());
|
||||
assertEquals(Arrays.asList(holdBulkStatus),
|
||||
holdBulkStatusCollection.getEntries().stream().map(HoldBulkStatusEntry::getEntry).toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a folder and all subfolders to a hold using the bulk API
|
||||
* Then the content is added to the hold and the status of the bulk operation is DONE
|
||||
*/
|
||||
@Test
|
||||
public void addContentFromFolderAndAllSubfoldersToHoldUsingBulkAPI()
|
||||
{
|
||||
hold3 = getRestAPIFactory().getFilePlansAPI(getAdminUser()).createHold(
|
||||
Hold.builder().name("HOLD" + generateTestPrefix(AddToHoldsV1Tests.class)).description(HOLD_DESCRIPTION)
|
||||
.reason(HOLD_REASON).build(), FILE_PLAN_ALIAS);
|
||||
holds.add(hold3);
|
||||
|
||||
UserModel userAddHoldPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole.SiteCollaborator, hold3.getId(), UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
|
||||
users.add(userAddHoldPermission);
|
||||
|
||||
STEP("Add content from the site to the hold using the bulk API.");
|
||||
// Get content from folder and all subfolders of the root folder
|
||||
HoldBulkOperation bulkOperation = HoldBulkOperation.builder()
|
||||
.query(getContentFromFolderAndAllSubfoldersQuery(rootFolder.getNodeRefWithoutVersion()))
|
||||
.op(HoldBulkOperationType.ADD).build();
|
||||
HoldBulkOperationEntry bulkOperationEntry = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.startBulkProcess(bulkOperation, hold3.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(ACCEPTED);
|
||||
assertEquals(NUMBER_OF_FILES, bulkOperationEntry.getTotalItems());
|
||||
|
||||
STEP("Wait until all files are added to the hold.");
|
||||
await().atMost(20, TimeUnit.SECONDS).until(
|
||||
() -> getRestAPIFactory().getHoldsAPI(getAdminUser()).getChildren(hold3.getId()).getEntries().size()
|
||||
== NUMBER_OF_FILES);
|
||||
List<String> holdChildrenNodeRefs = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getChildren(hold3.getId()).getEntries().stream().map(HoldChildEntry::getEntry).map(
|
||||
HoldChild::getId).toList();
|
||||
assertEquals(addedFiles.stream().map(FileModel::getNodeRefWithoutVersion).sorted().toList(),
|
||||
holdChildrenNodeRefs.stream().sorted().toList());
|
||||
|
||||
STEP("Check the bulk status.");
|
||||
HoldBulkStatus holdBulkStatus = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getBulkStatus(hold3.getId(), bulkOperationEntry.getBulkStatusId());
|
||||
assertBulkProcessStatus(holdBulkStatus, NUMBER_OF_FILES, 0, null, bulkOperation);
|
||||
|
||||
STEP("Check the bulk statuses.");
|
||||
HoldBulkStatusCollection holdBulkStatusCollection = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getBulkStatuses(hold3.getId());
|
||||
assertEquals(List.of(holdBulkStatus),
|
||||
holdBulkStatusCollection.getEntries().stream().map(HoldBulkStatusEntry::getEntry).toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user without the add to hold capability
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* Then the user receives access denied error
|
||||
*/
|
||||
@Test
|
||||
public void testBulkProcessWithUserWithoutAddToHoldCapability()
|
||||
{
|
||||
UserModel userWithoutAddToHoldCapability = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole
|
||||
.SiteCollaborator,
|
||||
hold.getId(), UserRoles.ROLE_RM_POWER_USER, PERMISSION_FILING);
|
||||
users.add(userWithoutAddToHoldCapability);
|
||||
|
||||
STEP("Add content from the site to the hold using the bulk API.");
|
||||
getRestAPIFactory().getHoldsAPI(userWithoutAddToHoldCapability)
|
||||
.startBulkProcess(holdBulkOperation, hold.getId());
|
||||
|
||||
STEP("Verify the response status code and the error message.");
|
||||
assertStatusCode(FORBIDDEN);
|
||||
getRestAPIFactory().getRmRestWrapper().assertLastError().containsSummary(ACCESS_DENIED_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user without the filing permission on a hold
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* Then the user receives access denied error
|
||||
*/
|
||||
@Test
|
||||
public void testBulkProcessWithUserWithoutFilingPermissionOnAHold()
|
||||
{
|
||||
// User without filing permission on a hold
|
||||
UserModel userWithoutPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole.SiteCollaborator, hold.getId(), UserRoles.ROLE_RM_MANAGER, PERMISSION_READ_RECORDS);
|
||||
users.add(userWithoutPermission);
|
||||
|
||||
STEP("Add content from the site to the hold using the bulk API.");
|
||||
getRestAPIFactory().getHoldsAPI(userWithoutPermission)
|
||||
.startBulkProcess(holdBulkOperation, hold.getId());
|
||||
|
||||
STEP("Verify the response status code and the error message.");
|
||||
assertStatusCode(FORBIDDEN);
|
||||
getRestAPIFactory().getRmRestWrapper().assertLastError().containsSummary(ACCESS_DENIED_ERROR_MESSAGE);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user without the write permission on all the content
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* Then all processed items are marked as errors and the last error message contains access denied error
|
||||
*/
|
||||
@Test
|
||||
public void testBulkProcessWithUserWithoutWritePermissionOnTheContent()
|
||||
{
|
||||
// User without write permission on the content
|
||||
UserModel userWithoutPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(
|
||||
testSite, UserRole.SiteConsumer,
|
||||
hold.getId(), UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
|
||||
users.add(userWithoutPermission);
|
||||
|
||||
// Wait until permissions are reverted
|
||||
SearchRequest searchRequest = new SearchRequest();
|
||||
searchRequest.setQuery(holdBulkOperation.getQuery());
|
||||
await().atMost(30, TimeUnit.SECONDS)
|
||||
.until(() -> getRestAPIFactory().getSearchAPI(userWithoutPermission).search(searchRequest).getPagination()
|
||||
.getTotalItems() == NUMBER_OF_FILES);
|
||||
|
||||
STEP("Add content from the site to the hold using the bulk API.");
|
||||
HoldBulkOperationEntry bulkOperationEntry = getRestAPIFactory().getHoldsAPI(
|
||||
userWithoutPermission).startBulkProcess(holdBulkOperation, hold.getId());
|
||||
|
||||
STEP("Verify the response.");
|
||||
assertStatusCode(ACCEPTED);
|
||||
|
||||
await().atMost(20, TimeUnit.SECONDS).until(() ->
|
||||
Objects.equals(getRestAPIFactory().getHoldsAPI(userWithoutPermission)
|
||||
.getBulkStatus(hold.getId(), bulkOperationEntry.getBulkStatusId()).getStatus(), "DONE"));
|
||||
|
||||
HoldBulkStatus holdBulkStatus = getRestAPIFactory().getHoldsAPI(userWithoutPermission)
|
||||
.getBulkStatus(hold.getId(), bulkOperationEntry.getBulkStatusId());
|
||||
assertBulkProcessStatus(holdBulkStatus, NUMBER_OF_FILES, NUMBER_OF_FILES, ACCESS_DENIED_ERROR_MESSAGE,
|
||||
holdBulkOperation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user without the write permission on one file
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* Then all processed items are added to the hold except the one that the user does not have write permission
|
||||
* And the status of the bulk operation is DONE, contains the error message and the number of errors is 1
|
||||
*/
|
||||
@Test
|
||||
public void testBulkProcessWithUserWithoutWritePermissionOnOneFile()
|
||||
{
|
||||
hold2 = getRestAPIFactory().getFilePlansAPI(getAdminUser()).createHold(
|
||||
Hold.builder().name("HOLD" + generateTestPrefix(AddToHoldsV1Tests.class)).description(HOLD_DESCRIPTION)
|
||||
.reason(HOLD_REASON).build(), FILE_PLAN_ALIAS);
|
||||
holds.add(hold2);
|
||||
|
||||
UserModel userAddHoldPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole.SiteCollaborator, hold2.getId(), UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
|
||||
users.add(userAddHoldPermission);
|
||||
|
||||
contentActions.setPermissionForUser(getAdminUser().getUsername(), getAdminUser().getPassword(),
|
||||
testSite.getId(), addedFiles.get(0).getName(), userAddHoldPermission.getUsername(),
|
||||
UserRole.SiteConsumer.getRoleId(), false);
|
||||
|
||||
STEP("Add content from the site to the hold using the bulk API.");
|
||||
HoldBulkOperationEntry bulkOperationEntry = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.startBulkProcess(holdBulkOperation, hold2.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(ACCEPTED);
|
||||
assertEquals(NUMBER_OF_FILES, bulkOperationEntry.getTotalItems());
|
||||
|
||||
STEP("Wait until all files are added to the hold.");
|
||||
await().atMost(30, TimeUnit.SECONDS).until(
|
||||
() -> getRestAPIFactory().getHoldsAPI(getAdminUser()).getChildren(hold2.getId()).getEntries().size()
|
||||
== NUMBER_OF_FILES - 1);
|
||||
await().atMost(30, TimeUnit.SECONDS).until(
|
||||
() -> getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getBulkStatus(hold2.getId(), bulkOperationEntry.getBulkStatusId()).getProcessedItems()
|
||||
== NUMBER_OF_FILES);
|
||||
List<String> holdChildrenNodeRefs = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getChildren(hold2.getId()).getEntries().stream().map(HoldChildEntry::getEntry).map(
|
||||
HoldChild::getId).toList();
|
||||
assertEquals(addedFiles.stream().skip(1).map(FileModel::getNodeRefWithoutVersion).sorted().toList(),
|
||||
holdChildrenNodeRefs.stream().sorted().toList());
|
||||
|
||||
STEP("Check the bulk status.");
|
||||
HoldBulkStatus holdBulkStatus = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getBulkStatus(hold2.getId(), bulkOperationEntry.getBulkStatusId());
|
||||
assertBulkProcessStatus(holdBulkStatus, NUMBER_OF_FILES, 1, ACCESS_DENIED_ERROR_MESSAGE, holdBulkOperation);
|
||||
|
||||
STEP("Check the bulk statuses.");
|
||||
HoldBulkStatusCollection holdBulkStatusCollection = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.getBulkStatuses(hold2.getId());
|
||||
assertEquals(List.of(holdBulkStatus),
|
||||
holdBulkStatusCollection.getEntries().stream().map(HoldBulkStatusEntry::getEntry).toList());
|
||||
|
||||
// Revert the permissions
|
||||
contentActions.setPermissionForUser(getAdminUser().getUsername(), getAdminUser().getPassword(),
|
||||
testSite.getId(), addedFiles.get(0).getName(), userAddHoldPermission.getUsername(),
|
||||
UserRole.SiteCollaborator.getRoleId(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an unauthenticated user
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* Then the user receives unauthorized error
|
||||
*/
|
||||
@Test
|
||||
public void testBulkProcessAsUnauthenticatedUser()
|
||||
{
|
||||
STEP("Start bulk process as unauthenticated user");
|
||||
getRestAPIFactory().getHoldsAPI(new UserModel(getAdminUser().getUsername(), "wrongPassword"))
|
||||
.startBulkProcess(holdBulkOperation, hold.getId());
|
||||
|
||||
STEP("Verify the response status code.");
|
||||
assertStatusCode(UNAUTHORIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* And the hold does not exist
|
||||
* Then the user receives not found error
|
||||
*/
|
||||
@Test
|
||||
public void testBulkProcessForNonExistentHold()
|
||||
{
|
||||
STEP("Start bulk process for non existent hold");
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser()).startBulkProcess(holdBulkOperation, "nonExistentHoldId");
|
||||
|
||||
STEP("Verify the response status code.");
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* and the bulk operation is invalid
|
||||
* Then the user receives bad request error
|
||||
*/
|
||||
@Test
|
||||
public void testGetBulkStatusesForInvalidOperation()
|
||||
{
|
||||
STEP("Start bulk process for non existent hold");
|
||||
|
||||
HoldBulkOperation invalidHoldBulkOperation = HoldBulkOperation.builder().op(null)
|
||||
.query(holdBulkOperation.getQuery()).build();
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser()).startBulkProcess(invalidHoldBulkOperation, hold.getId());
|
||||
|
||||
STEP("Verify the response status code.");
|
||||
assertStatusCode(BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* And the hold does not exist
|
||||
* Then the user receives not found error
|
||||
*/
|
||||
@Test
|
||||
public void testGetBulkStatusForNonExistentHold()
|
||||
{
|
||||
STEP("Start bulk process for non existent hold");
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser()).getBulkStatus("nonExistentHoldId", "nonExistenBulkStatusId");
|
||||
|
||||
STEP("Verify the response status code.");
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* And the bulk status does not exist
|
||||
* Then the user receives not found error
|
||||
*/
|
||||
@Test
|
||||
public void testGetBulkStatusForNonExistentBulkStatus()
|
||||
{
|
||||
STEP("Start bulk process for non bulk status");
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser()).getBulkStatus(hold.getId(), "nonExistenBulkStatusId");
|
||||
|
||||
STEP("Verify the response status code.");
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* And the hold does not exist
|
||||
* Then the user receives not found error
|
||||
*/
|
||||
@Test
|
||||
public void testGetBulkStatusesForNonExistentHold()
|
||||
{
|
||||
STEP("Start bulk process for non existent hold");
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser()).getBulkStatuses("nonExistentHoldId");
|
||||
|
||||
STEP("Verify the response status code.");
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from all sites to a hold using the bulk API to exceed the limit (30 items)
|
||||
* Then the user receives bad request error
|
||||
*/
|
||||
@Test
|
||||
public void testExceedingBulkOperationLimit()
|
||||
{
|
||||
RestRequestQueryModel queryReq = new RestRequestQueryModel();
|
||||
queryReq.setQuery("TYPE:content");
|
||||
queryReq.setLanguage("afts");
|
||||
|
||||
HoldBulkOperation exceedLimitOp = HoldBulkOperation.builder()
|
||||
.query(queryReq)
|
||||
.op(HoldBulkOperationType.ADD).build();
|
||||
|
||||
STEP("Start bulk process to exceed the limit");
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser()).startBulkProcess(exceedLimitOp, hold.getId());
|
||||
|
||||
STEP("Verify the response status code.");
|
||||
assertStatusCode(BAD_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* And then the user cancels the bulk operation
|
||||
* Then the user receives OK status code
|
||||
*/
|
||||
@Test
|
||||
public void testBulkProcessCancellationWithAllowedUser()
|
||||
{
|
||||
Hold hold4 = getRestAPIFactory().getFilePlansAPI(getAdminUser()).createHold(
|
||||
Hold.builder().name("HOLD" + generateTestPrefix(AddToHoldsV1Tests.class)).description(HOLD_DESCRIPTION)
|
||||
.reason(HOLD_REASON).build(), FILE_PLAN_ALIAS);
|
||||
holds.add(hold4);
|
||||
|
||||
UserModel userAddHoldPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole.SiteCollaborator, hold4.getId(), UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
|
||||
users.add(userAddHoldPermission);
|
||||
|
||||
STEP("Add content from the site to the hold using the bulk API.");
|
||||
HoldBulkOperationEntry bulkOperationEntry = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.startBulkProcess(holdBulkOperation, hold4.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(ACCEPTED);
|
||||
assertEquals(NUMBER_OF_FILES, bulkOperationEntry.getTotalItems());
|
||||
|
||||
STEP("Cancel the bulk operation.");
|
||||
getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.cancelBulkOperation(hold4.getId(), bulkOperationEntry.getBulkStatusId(), new BulkBodyCancel());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a user with the add to hold capability and hold filing permission
|
||||
* When the user adds content from a site to a hold using the bulk API
|
||||
* And a 2nd user without the add to hold capability cancels the bulk operation
|
||||
* Then the 2nd user receives access denied error
|
||||
*/
|
||||
@Test
|
||||
public void testBulkProcessCancellationWithUserWithoutAddToHoldCapability()
|
||||
{
|
||||
Hold hold5 = getRestAPIFactory().getFilePlansAPI(getAdminUser()).createHold(
|
||||
Hold.builder().name("HOLD" + generateTestPrefix(AddToHoldsV1Tests.class)).description(HOLD_DESCRIPTION)
|
||||
.reason(HOLD_REASON).build(), FILE_PLAN_ALIAS);
|
||||
holds.add(hold5);
|
||||
|
||||
UserModel userAddHoldPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole.SiteCollaborator, hold5.getId(), UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
|
||||
users.add(userAddHoldPermission);
|
||||
|
||||
STEP("Add content from the site to the hold using the bulk API.");
|
||||
HoldBulkOperationEntry bulkOperationEntry = getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.startBulkProcess(holdBulkOperation, hold5.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(ACCEPTED);
|
||||
assertEquals(NUMBER_OF_FILES, bulkOperationEntry.getTotalItems());
|
||||
|
||||
UserModel userWithoutAddToHoldCapability = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole
|
||||
.SiteCollaborator,
|
||||
hold5.getId(), UserRoles.ROLE_RM_POWER_USER, PERMISSION_FILING);
|
||||
users.add(userWithoutAddToHoldCapability);
|
||||
|
||||
STEP("Cancel the bulk operation.");
|
||||
getRestAPIFactory().getHoldsAPI(userWithoutAddToHoldCapability)
|
||||
.cancelBulkOperation(hold5.getId(), bulkOperationEntry.getBulkStatusId(), new BulkBodyCancel());
|
||||
|
||||
STEP("Verify the response status code and the error message.");
|
||||
assertStatusCode(FORBIDDEN);
|
||||
getRestAPIFactory().getRmRestWrapper().assertLastError().containsSummary(ACCESS_DENIED_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
private void assertBulkProcessStatus(HoldBulkStatus holdBulkStatus, long expectedProcessedItems,
|
||||
int expectedErrorsCount, String expectedErrorMessage, HoldBulkOperation holdBulkOperation)
|
||||
{
|
||||
assertEquals("DONE", holdBulkStatus.getStatus());
|
||||
assertEquals(expectedProcessedItems, holdBulkStatus.getTotalItems());
|
||||
assertEquals(expectedProcessedItems, holdBulkStatus.getProcessedItems());
|
||||
assertEquals(expectedErrorsCount, holdBulkStatus.getErrorsCount());
|
||||
assertEquals(holdBulkStatus.getHoldBulkOperation(), holdBulkOperation);
|
||||
assertNotNull(holdBulkStatus.getStartTime());
|
||||
assertNotNull(holdBulkStatus.getEndTime());
|
||||
|
||||
if (expectedErrorMessage != null)
|
||||
{
|
||||
assertTrue(holdBulkStatus.getLastError().contains(expectedErrorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
private RestRequestQueryModel getContentFromSiteQuery(String siteId)
|
||||
{
|
||||
RestRequestQueryModel queryReq = new RestRequestQueryModel();
|
||||
queryReq.setQuery("SITE:\"" + siteId + "\" and TYPE:content");
|
||||
queryReq.setLanguage("afts");
|
||||
return queryReq;
|
||||
}
|
||||
|
||||
private RestRequestQueryModel getContentFromFolderAndAllSubfoldersQuery(String folderId)
|
||||
{
|
||||
RestRequestQueryModel queryReq = new RestRequestQueryModel();
|
||||
queryReq.setQuery("ANCESTOR:\"workspace://SpacesStore/" + folderId + "\" and TYPE:content");
|
||||
queryReq.setLanguage("afts");
|
||||
return queryReq;
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void cleanupAddToHoldsBulkV1Tests()
|
||||
{
|
||||
dataSite.usingAdmin().deleteSite(testSite);
|
||||
users.forEach(user -> getDataUser().usingAdmin().deleteUser(user));
|
||||
holds.forEach(hold -> getRestAPIFactory().getHoldsAPI(getAdminUser()).deleteHold(hold.getId()));
|
||||
}
|
||||
}
|
@@ -0,0 +1,377 @@
|
||||
/*-
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.retentionschedule;
|
||||
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionSchedule;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionScheduleActionDefinition;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionScheduleStepCollection;
|
||||
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
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.NOT_FOUND;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
|
||||
import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
|
||||
/**
|
||||
* Retention schedule step test case
|
||||
*/
|
||||
public class RetentionScheduleStepTests extends BaseRMRestTest
|
||||
{
|
||||
private RecordCategory recordCategory;
|
||||
private RetentionSchedule createdRetentionSchedule;
|
||||
private final RetentionScheduleActionDefinition retentionScheduleActionDefinition = new RetentionScheduleActionDefinition();
|
||||
private RetentionScheduleActionDefinition createdRetentionActionDefinition;
|
||||
private UserModel nonRMuser;
|
||||
private final List<String> recordCategories = new ArrayList<>();
|
||||
private static final String TEST_USER = "testUser";
|
||||
private static final String RECORD_CATEGORY = "recordCategory";
|
||||
private static final String PERIOD_PROPERTY = "cm:created";
|
||||
private static final String AUTHORITY = "authority";
|
||||
private static final String INSTRUCTIONS = "instructions";
|
||||
private static final int PERIOD_AMOUNT = 5;
|
||||
private static final String PERIOD = "month";
|
||||
private static final List<String> EVENTS = Arrays.asList("case_closed","abolished");
|
||||
private static final String TRANSFER_STEP = "transfer";
|
||||
private static final String RETAIN_STEP = "retain";
|
||||
private static final String INVALID_PERIOD = "random";
|
||||
private static final String CUTOFF_STEP = "cutoff";
|
||||
private static final String DESTROY_STEP = "destroyContent";
|
||||
private static final String INVALID_PASSWORD = "wrongPassword";
|
||||
|
||||
@Autowired
|
||||
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void preconditionForRetentionScheduleStepTests()
|
||||
{
|
||||
createRMSiteIfNotExists();
|
||||
// create a non rm user
|
||||
nonRMuser = dataUser.createRandomTestUser(TEST_USER);
|
||||
//Create record category
|
||||
recordCategory = createRootCategory(getRandomName(RECORD_CATEGORY));
|
||||
recordCategories.add(recordCategory.getId());
|
||||
RetentionSchedule retentionSchedule = new RetentionSchedule();
|
||||
retentionSchedule.setAuthority(AUTHORITY + getRandomAlphanumeric());
|
||||
retentionSchedule.setInstructions(INSTRUCTIONS + getRandomAlphanumeric());
|
||||
retentionSchedule.setIsRecordLevel(false);
|
||||
//Create retention schedule with a valid user
|
||||
createdRetentionSchedule = getRestAPIFactory().getRetentionScheduleAPI()
|
||||
.createRetentionSchedule(retentionSchedule, recordCategory.getId());
|
||||
|
||||
retentionScheduleActionDefinition.setName(RETAIN_STEP);
|
||||
retentionScheduleActionDefinition.setDescription(INSTRUCTIONS);
|
||||
retentionScheduleActionDefinition.setPeriodAmount(PERIOD_AMOUNT);
|
||||
retentionScheduleActionDefinition.setPeriodProperty(PERIOD_PROPERTY);
|
||||
retentionScheduleActionDefinition.setPeriod(PERIOD);
|
||||
retentionScheduleActionDefinition.setCombineRetentionStepConditions(false);
|
||||
retentionScheduleActionDefinition.setEligibleOnFirstCompleteEvent(true);
|
||||
retentionScheduleActionDefinition.setEvents(EVENTS);
|
||||
}
|
||||
|
||||
@Test(priority = 1)
|
||||
public void createRetentionScheduleStepFor422()
|
||||
{
|
||||
RetentionScheduleActionDefinition actionDefinition = getRetentionScheduleActionDefinition();
|
||||
//Creating the first action "transfer" should give 422
|
||||
actionDefinition.setName(TRANSFER_STEP);
|
||||
actionDefinition.setLocation("location");
|
||||
//Create retention schedule action definition
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition,createdRetentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
@Test(priority = 2)
|
||||
public void createRetentionScheduleStepWithInvalidPeriodValue()
|
||||
{
|
||||
RetentionScheduleActionDefinition actionDefinition = getRetentionScheduleActionDefinition();
|
||||
actionDefinition.setName(RETAIN_STEP);
|
||||
//Invalid period value
|
||||
actionDefinition.setPeriod(INVALID_PERIOD);
|
||||
//Create retention schedule action definition
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition,createdRetentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(BAD_REQUEST);
|
||||
}
|
||||
|
||||
@Test(priority = 3)
|
||||
public void createRetentionScheduleWithInvalidStep()
|
||||
{
|
||||
RecordCategory recordCategory = createRootCategory(getRandomName(RECORD_CATEGORY));
|
||||
recordCategories.add(recordCategory.getId());
|
||||
RetentionSchedule retentionSchedule = createRetentionSchedule(recordCategory);
|
||||
RetentionScheduleActionDefinition actionDefinition = getRetentionScheduleActionDefinition();
|
||||
actionDefinition.setName(RETAIN_STEP);
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition,retentionSchedule.getId());
|
||||
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
RetentionScheduleActionDefinition actionDefinition1 = getRetentionScheduleActionDefinition();
|
||||
actionDefinition1.setName(TRANSFER_STEP);
|
||||
actionDefinition1.setLocation("location");
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition1,retentionSchedule.getId());
|
||||
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
RetentionScheduleActionDefinition actionDefinition2 = getRetentionScheduleActionDefinition();
|
||||
actionDefinition2.setName(CUTOFF_STEP);
|
||||
//Create retention schedule action definition
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition2,retentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(CONFLICT);
|
||||
}
|
||||
|
||||
@Test(priority = 4)
|
||||
public void createRetentionScheduleWithInvalidStepAfterDestroy()
|
||||
{
|
||||
RecordCategory recordCategory = createRootCategory(getRandomName(RECORD_CATEGORY));
|
||||
recordCategories.add(recordCategory.getId());
|
||||
RetentionSchedule retentionSchedule = createRetentionSchedule(recordCategory);
|
||||
RetentionScheduleActionDefinition actionDefinition = getRetentionScheduleActionDefinition();
|
||||
actionDefinition.setName(RETAIN_STEP);
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition,retentionSchedule.getId());
|
||||
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
RetentionScheduleActionDefinition actionDefinition1 = getRetentionScheduleActionDefinition();
|
||||
actionDefinition1.setName(DESTROY_STEP);
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition1,retentionSchedule.getId());
|
||||
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
RetentionScheduleActionDefinition actionDefinition2 = getRetentionScheduleActionDefinition();
|
||||
actionDefinition2.setName(CUTOFF_STEP);
|
||||
//Create retention schedule action definition
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition2,retentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(CONFLICT);
|
||||
}
|
||||
|
||||
@Test(priority = 5)
|
||||
public void combineRetentionStepConditionsNotValidForNonAccessionStep()
|
||||
{
|
||||
RecordCategory recordCategory = createRootCategory(getRandomName(RECORD_CATEGORY));
|
||||
recordCategories.add(recordCategory.getId());
|
||||
RetentionSchedule retentionSchedule = createRetentionSchedule(recordCategory);
|
||||
RetentionScheduleActionDefinition actionDefinition = getRetentionScheduleActionDefinition();
|
||||
actionDefinition.setName(RETAIN_STEP);
|
||||
actionDefinition.setCombineRetentionStepConditions(true);
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition,retentionSchedule.getId());
|
||||
|
||||
assertStatusCode(BAD_REQUEST);
|
||||
}
|
||||
|
||||
@Test(priority = 6)
|
||||
public void createRetentionScheduleWithSameStep()
|
||||
{
|
||||
RecordCategory recordCategory = createRootCategory(getRandomName(RECORD_CATEGORY));
|
||||
recordCategories.add(recordCategory.getId());
|
||||
RetentionSchedule retentionSchedule = createRetentionSchedule(recordCategory);
|
||||
RetentionScheduleActionDefinition actionDefinition = getRetentionScheduleActionDefinition();
|
||||
actionDefinition.setName(RETAIN_STEP);
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition,retentionSchedule.getId());
|
||||
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
RetentionScheduleActionDefinition actionDefinition1 = getRetentionScheduleActionDefinition();
|
||||
actionDefinition1.setName(RETAIN_STEP);
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition1,retentionSchedule.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(CONFLICT);
|
||||
}
|
||||
|
||||
@Test(priority = 7)
|
||||
public void createRetentionScheduleWithMultipleTransferStep()
|
||||
{
|
||||
RecordCategory recordCategory = createRootCategory(getRandomName(RECORD_CATEGORY));
|
||||
recordCategories.add(recordCategory.getId());
|
||||
RetentionSchedule retentionSchedule = createRetentionSchedule(recordCategory);
|
||||
RetentionScheduleActionDefinition actionDefinition = getRetentionScheduleActionDefinition();
|
||||
actionDefinition.setName(RETAIN_STEP);
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition,retentionSchedule.getId());
|
||||
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
RetentionScheduleActionDefinition actionDefinition1 = getRetentionScheduleActionDefinition();
|
||||
actionDefinition1.setName(TRANSFER_STEP);
|
||||
actionDefinition1.setLocation("location");
|
||||
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition1, retentionSchedule.getId());
|
||||
|
||||
RetentionScheduleActionDefinition actionDefinition2 = getRetentionScheduleActionDefinition();
|
||||
actionDefinition2.setName(TRANSFER_STEP);
|
||||
actionDefinition2.setLocation("location");
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(actionDefinition2, retentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(CREATED);
|
||||
}
|
||||
|
||||
@Test(priority = 8)
|
||||
public void createRetentionScheduleStepFor201()
|
||||
{
|
||||
//Create retention schedule action definition
|
||||
createdRetentionActionDefinition = getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(retentionScheduleActionDefinition,createdRetentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(CREATED);
|
||||
// Find this retention schedule is created one or not
|
||||
assertEquals(createdRetentionActionDefinition.getName(), retentionScheduleActionDefinition.getName());
|
||||
assertEquals(createdRetentionActionDefinition.getDescription(), retentionScheduleActionDefinition.getDescription());
|
||||
assertEquals(createdRetentionActionDefinition.getPeriodAmount(), retentionScheduleActionDefinition.getPeriodAmount());
|
||||
assertEquals(createdRetentionActionDefinition.isCombineRetentionStepConditions(), retentionScheduleActionDefinition.isCombineRetentionStepConditions());
|
||||
assertEquals(createdRetentionActionDefinition.isEligibleOnFirstCompleteEvent(), retentionScheduleActionDefinition.isEligibleOnFirstCompleteEvent());
|
||||
}
|
||||
|
||||
@Test(priority = 9)
|
||||
public void createRetentionScheduleStepFor401()
|
||||
{
|
||||
//Create retention schedule action definition
|
||||
getRestAPIFactory().getRetentionScheduleAPI(new UserModel(getAdminUser().getUsername(), INVALID_PASSWORD)).createRetentionScheduleStep(retentionScheduleActionDefinition,createdRetentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test(priority = 10)
|
||||
public void createRetentionScheduleStepFor403()
|
||||
{
|
||||
//Create retention schedule action definition
|
||||
getRestAPIFactory().getRetentionScheduleAPI(nonRMuser).createRetentionScheduleStep(retentionScheduleActionDefinition,createdRetentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(FORBIDDEN);
|
||||
}
|
||||
|
||||
@Test(priority = 11)
|
||||
public void retentionScheduleStepFor400()
|
||||
{
|
||||
getRestAPIFactory().getRetentionScheduleAPI().getRetentionScheduleStep(recordCategory.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(BAD_REQUEST);
|
||||
}
|
||||
|
||||
@Test(priority = 12)
|
||||
public void createRetentionScheduleStepFor404()
|
||||
{
|
||||
//Create retention schedule action definition
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionScheduleStep(retentionScheduleActionDefinition,getRandomAlphanumeric());
|
||||
// Verify the status code
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test(priority = 13)
|
||||
public void retentionScheduleStepFor403()
|
||||
{
|
||||
// Get retention schedule steps with user having no rights
|
||||
getRestAPIFactory().getRetentionScheduleAPI(nonRMuser).getRetentionScheduleStep(createdRetentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(FORBIDDEN);
|
||||
}
|
||||
|
||||
@Test(priority = 14)
|
||||
public void retentionScheduleStepFor401()
|
||||
{
|
||||
getRestAPIFactory().getRetentionScheduleAPI(new UserModel(getAdminUser().getUsername(), INVALID_PASSWORD)).getRetentionScheduleStep(createdRetentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@Test(priority = 15)
|
||||
public void retentionScheduleStepWith200()
|
||||
{
|
||||
RetentionScheduleStepCollection receiveRetentionStepCollection = getRestAPIFactory().getRetentionScheduleAPI().getRetentionScheduleStep(createdRetentionSchedule.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(OK);
|
||||
receiveRetentionStepCollection.getEntries().forEach(c ->
|
||||
{
|
||||
RetentionScheduleActionDefinition retentionActionDef = c.getEntry();
|
||||
assertNotNull(retentionActionDef.getId());
|
||||
// Find this retention schedule is created one or not
|
||||
assertEquals(createdRetentionActionDefinition.getId(), retentionActionDef.getId());
|
||||
assertEquals(createdRetentionActionDefinition.getName(), retentionActionDef.getName());
|
||||
assertEquals(createdRetentionActionDefinition.getDescription(), retentionActionDef.getDescription());
|
||||
assertEquals(createdRetentionActionDefinition.getPeriod(), retentionActionDef.getPeriod());
|
||||
assertEquals(createdRetentionActionDefinition.getPeriodAmount(), retentionActionDef.getPeriodAmount());
|
||||
assertEquals(createdRetentionActionDefinition.isCombineRetentionStepConditions(), retentionActionDef.isCombineRetentionStepConditions());
|
||||
assertEquals(createdRetentionActionDefinition.isEligibleOnFirstCompleteEvent(), retentionActionDef.isEligibleOnFirstCompleteEvent());
|
||||
});
|
||||
}
|
||||
|
||||
private RetentionSchedule createRetentionSchedule(RecordCategory recordCategory)
|
||||
{
|
||||
RetentionSchedule retentionSchedule = new RetentionSchedule();
|
||||
retentionSchedule.setAuthority(AUTHORITY + getRandomAlphanumeric());
|
||||
retentionSchedule.setInstructions(INSTRUCTIONS + getRandomAlphanumeric());
|
||||
retentionSchedule.setIsRecordLevel(false);
|
||||
//Create retention schedule with a valid user
|
||||
retentionSchedule = getRestAPIFactory().getRetentionScheduleAPI()
|
||||
.createRetentionSchedule(retentionSchedule, recordCategory.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(CREATED);
|
||||
return retentionSchedule;
|
||||
}
|
||||
|
||||
private static RetentionScheduleActionDefinition getRetentionScheduleActionDefinition()
|
||||
{
|
||||
RetentionScheduleActionDefinition actionDefinition = new RetentionScheduleActionDefinition();
|
||||
actionDefinition.setDescription(INSTRUCTIONS);
|
||||
actionDefinition.setPeriodAmount(PERIOD_AMOUNT);
|
||||
actionDefinition.setPeriodProperty(PERIOD_PROPERTY);
|
||||
actionDefinition.setPeriod(PERIOD);
|
||||
actionDefinition.setCombineRetentionStepConditions(false);
|
||||
actionDefinition.setEligibleOnFirstCompleteEvent(true);
|
||||
actionDefinition.setEvents(EVENTS);
|
||||
return actionDefinition;
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void cleanUpRetentionScheduleStepTests()
|
||||
{
|
||||
rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, recordCategory.getName());
|
||||
recordCategories.forEach(this::deleteRecordCategory);
|
||||
dataUser.deleteUser(nonRMuser);
|
||||
}
|
||||
}
|
@@ -0,0 +1,270 @@
|
||||
/*-
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.community.retentionschedule;
|
||||
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionSchedule;
|
||||
import org.alfresco.rest.rm.community.model.retentionschedule.RetentionScheduleCollection;
|
||||
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.alfresco.rest.core.v0.BaseAPI.RM_SITE_ID;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
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.NOT_FOUND;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
|
||||
/**
|
||||
* This class contains the tests for the Retention Schedule CRUD V1 API
|
||||
*/
|
||||
public class RetentionScheduleTests extends BaseRMRestTest
|
||||
{
|
||||
private RecordCategory recordCategory;
|
||||
private RetentionSchedule createdRetentionSchedule;
|
||||
private UserModel nonRMuser;
|
||||
@Autowired
|
||||
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void preconditionForRetentionScheduleTests()
|
||||
{
|
||||
createRMSiteIfNotExists();
|
||||
// create a non rm user
|
||||
nonRMuser = dataUser.createRandomTestUser("testUser");
|
||||
//Create record category
|
||||
recordCategory = createRootCategory(getRandomName("recordCategory"));
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category exists
|
||||
* When I ask the API to create a retention schedule with a user having no rights
|
||||
* Then it will give 403 as status code
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 1)
|
||||
public void createRetentionScheduleFor403()
|
||||
{
|
||||
RetentionSchedule retentionSchedule = new RetentionSchedule();
|
||||
|
||||
// Create retention schedule with user having no rights
|
||||
getRestAPIFactory().getRetentionScheduleAPI(nonRMuser).createRetentionSchedule(retentionSchedule, recordCategory.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(FORBIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category does not exists
|
||||
* When I ask the API to create a retention schedule on a category Id
|
||||
* Then it will give 404 as a status code
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 2)
|
||||
public void createRetentionScheduleFor404()
|
||||
{
|
||||
RetentionSchedule retentionSchedule = new RetentionSchedule();
|
||||
|
||||
//Create retention schedule with category id not exist
|
||||
getRestAPIFactory().getRetentionScheduleAPI().createRetentionSchedule(retentionSchedule, getRandomAlphanumeric());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category exists
|
||||
* When I ask the API to create a retention schedule on a category id with a user having unauthorized access
|
||||
* Then it will give 401 as a status code
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 3)
|
||||
public void createRetentionScheduleFor401()
|
||||
{
|
||||
RetentionSchedule retentionSchedule = new RetentionSchedule();
|
||||
|
||||
//Create retention schedule with a user with unauthorized access
|
||||
createdRetentionSchedule = getRestAPIFactory().getRetentionScheduleAPI(new UserModel(getAdminUser().getUsername(), "wrongPassword")).createRetentionSchedule(retentionSchedule, recordCategory.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(UNAUTHORIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category exists
|
||||
* When I ask the API to create a retention schedule with a user having access
|
||||
* Then it is created with a 201 status code
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 4)
|
||||
public void createRetentionScheduleFor201()
|
||||
{
|
||||
RetentionSchedule retentionSchedule = new RetentionSchedule();
|
||||
String authority = "authority" + getRandomAlphanumeric();
|
||||
String instructions = "instructions" + getRandomAlphanumeric();
|
||||
boolean isRecordLevel = false;
|
||||
retentionSchedule.setAuthority(authority);
|
||||
retentionSchedule.setInstructions(instructions);
|
||||
retentionSchedule.setIsRecordLevel(isRecordLevel);
|
||||
|
||||
//Create retention schedule with a valid user
|
||||
createdRetentionSchedule = getRestAPIFactory().getRetentionScheduleAPI()
|
||||
.createRetentionSchedule(retentionSchedule, recordCategory.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(CREATED);
|
||||
assertEquals(createdRetentionSchedule.getAuthority(), authority);
|
||||
assertEquals(createdRetentionSchedule.getInstructions(), instructions);
|
||||
assertFalse(createdRetentionSchedule.getIsRecordLevel());
|
||||
assertNotNull(createdRetentionSchedule.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category exists
|
||||
* When I ask the API to create a retention schedule on a category id having retention schedule already
|
||||
* Then it will give 409 as a status code
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 5)
|
||||
public void createRetentionScheduleFor409()
|
||||
{
|
||||
RetentionSchedule retentionSchedule = new RetentionSchedule();
|
||||
//Create retention schedule on a category with already having retention schedule
|
||||
getRestAPIFactory().getRetentionScheduleAPI()
|
||||
.createRetentionSchedule(retentionSchedule, recordCategory.getId());
|
||||
|
||||
assertStatusCode(CONFLICT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category exists
|
||||
* When I ask the API to get a retention schedule on a given categoryId with a user having no rights
|
||||
* Then it will give 403
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 6)
|
||||
public void retentionScheduleWith403()
|
||||
{
|
||||
//Get retention schedule with user having no rights
|
||||
getRestAPIFactory().getRetentionScheduleAPI(nonRMuser).getRetentionSchedule(recordCategory.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(FORBIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category does not exists
|
||||
* When I ask the API to get a retention schedule on a category Id
|
||||
* Then it will give 404 as a status code
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 7)
|
||||
public void retentionScheduleWith404()
|
||||
{
|
||||
|
||||
//Get retention schedule with category id that does not exist
|
||||
getRestAPIFactory().getRetentionScheduleAPI().getRetentionSchedule(getRandomAlphanumeric());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category exists
|
||||
* When I ask the API to get a retention schedule on a categoryId with a user having unauthorized access
|
||||
* Then it will give 401 as a status code
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 8)
|
||||
public void retentionScheduleWith401()
|
||||
{
|
||||
//Create retention schedule with a user with unauthorized access
|
||||
getRestAPIFactory().getRetentionScheduleAPI(new UserModel(getAdminUser().getUsername(), "wrongPassword")).getRetentionSchedule(recordCategory.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(UNAUTHORIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a record category exists
|
||||
* When I ask the API to get a retention schedule on a categoryId with a user having access
|
||||
* Then it will give retentionSchedule with 200 as a status code
|
||||
* </pre>
|
||||
*/
|
||||
@Test(priority = 9)
|
||||
public void retentionScheduleWith200()
|
||||
{
|
||||
RetentionScheduleCollection retentionScheduleCollection = getRestAPIFactory().getRetentionScheduleAPI().getRetentionSchedule(recordCategory.getId());
|
||||
// Verify the status code
|
||||
assertStatusCode(OK);
|
||||
retentionScheduleCollection.getEntries().forEach(c ->
|
||||
{
|
||||
RetentionSchedule retentionSchedule = c.getEntry();
|
||||
String retentionScheduleId = retentionSchedule.getId();
|
||||
assertNotNull(retentionScheduleId);
|
||||
logger.info("Checking retention schedule " + retentionScheduleId);
|
||||
|
||||
// Find this retention schedule is created one or not
|
||||
assertEquals(createdRetentionSchedule.getId(), retentionScheduleId);
|
||||
assertEquals(createdRetentionSchedule.getParentId(),retentionSchedule.getParentId());
|
||||
assertEquals(createdRetentionSchedule.getAuthority(), retentionSchedule.getAuthority());
|
||||
assertEquals(createdRetentionSchedule.getInstructions(), retentionSchedule.getInstructions());
|
||||
assertEquals(createdRetentionSchedule.getIsRecordLevel(), retentionSchedule.getIsRecordLevel());
|
||||
assertEquals(createdRetentionSchedule.isUnpublishedUpdates(), retentionSchedule.isUnpublishedUpdates());
|
||||
});
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void cleanUpRetentionScheduleTests()
|
||||
{
|
||||
rmRolesAndActionsAPI.deleteAllItemsInContainer(getDataUser().usingAdmin().getAdminUser().getUsername(),
|
||||
getDataUser().usingAdmin().getAdminUser().getPassword(), RM_SITE_ID, recordCategory.getName());
|
||||
deleteRecordCategory(recordCategory.getId());
|
||||
dataUser.deleteUser(nonRMuser);
|
||||
}
|
||||
}
|
@@ -45,9 +45,9 @@ serverHealth.showTenants=false
|
||||
# testManagement.username=<username>
|
||||
# testManagement.apiKey=<api-key>
|
||||
# testManagement.project=<id-of-your-project
|
||||
# testManagement.testRun=<test-run-name>
|
||||
# testManagement.testRun=<test-run-name>
|
||||
# testManagement.includeOnlyTestCasesExecuted=true #if you want to include in your run ONLY the test cases that you run, then set this value to false
|
||||
# testManagement.rateLimitInSeconds=1 #is the default rate limit after what minimum time, should we upload the next request. http://docs.gurock.com/testrail-api2/introduction #Rate Limit
|
||||
# testManagement.rateLimitInSeconds=1 #is the default rate limit after what minimum time, should we upload the next request. http://docs.gurock.com/testrail-api2/introduction #Rate Limit
|
||||
# testManagement.suiteId=23 (the id of the Master suite)
|
||||
# ------------------------------------------------------
|
||||
testManagement.enabled=false
|
||||
@@ -72,7 +72,7 @@ reports.path=./target/reports
|
||||
#
|
||||
# MySQL:
|
||||
# db.url = jdbc:mysql://${alfresco.server}:3306/alfresco
|
||||
#
|
||||
#
|
||||
# PostgreSQL:
|
||||
# db.url = jdbc:postgresql://<your-DB-IP>:3306/alfresco
|
||||
#
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -1,3 +1,3 @@
|
||||
SOLR6_TAG=2.0.10
|
||||
SOLR6_TAG=2.0.12
|
||||
POSTGRES_TAG=15.4
|
||||
ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8
|
||||
|
@@ -139,3 +139,26 @@ content.metadata.async.extract.6.enabled=false
|
||||
|
||||
# Max number of entries returned in Record search view
|
||||
rm.recordSearch.maxItems=500
|
||||
|
||||
#
|
||||
# Hold bulk
|
||||
#
|
||||
# The number of worker threads.
|
||||
rm.hold.bulk.threadCount=2
|
||||
# The maximum number of total items to process in a single bulk operation.
|
||||
rm.hold.bulk.maxItems=1000
|
||||
# The number of entries to be fetched from the Search Service as a next set of work object to process.
|
||||
rm.hold.bulk.batchSize=100
|
||||
# The number of entries to process before reporting progress.
|
||||
rm.hold.bulk.logging.interval=100
|
||||
# The number of entries we process at a time in a transaction.
|
||||
rm.hold.bulk.itemsPerTransaction=1
|
||||
# The maximum number of bulk requests we can process in parallel.
|
||||
rm.hold.bulk.maxParallelRequests=10
|
||||
|
||||
cache.bulkHoldStatusCache.cluster.type=fully-distributed
|
||||
cache.bulkHoldStatusCache.timeToLiveSeconds=2592000
|
||||
cache.bulkHoldRegistryCache.cluster.type=fully-distributed
|
||||
cache.bulkHoldRegistryCache.timeToLiveSeconds=2592000
|
||||
cache.bulkCancellationsCache.cluster.type=fully-distributed
|
||||
cache.bulkCancellationsCache.timeToLiveSeconds=2592000
|
@@ -31,6 +31,11 @@
|
||||
<cm:description>Configuration information for the Records Management application.</cm:description>
|
||||
</view:properties>
|
||||
|
||||
<view:aspects>
|
||||
<sys:undeletable/>
|
||||
<sys:unmovable/>
|
||||
</view:aspects>
|
||||
|
||||
<view:associations>
|
||||
<cm:contains>
|
||||
|
||||
|
@@ -125,7 +125,7 @@
|
||||
parent="declarativeCapability">
|
||||
<property name="name" value="DeleteRecordFolder"/>
|
||||
<property name="private" value="true"/>
|
||||
<property name="permission" value="CreateModifyDestroyFolders"/>
|
||||
<property name="permission" value="DeleteRecords"/>
|
||||
<property name="kinds">
|
||||
<list>
|
||||
<value>RECORD_FOLDER</value>
|
||||
|
@@ -89,6 +89,9 @@
|
||||
<!-- Import RM Audit -->
|
||||
<import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-audit-context.xml"/>
|
||||
|
||||
<!-- Import RM Bulk -->
|
||||
<import resource="classpath:alfresco/module/org_alfresco_module_rm/rm-bulk-context.xml"/>
|
||||
|
||||
<!-- Import RM query context -->
|
||||
<import resource="classpath:alfresco/module/org_alfresco_module_rm/query/rm-query-context.xml" />
|
||||
|
||||
|
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<bean id="holdBulkService"
|
||||
class="org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkServiceImpl">
|
||||
<property name="serviceRegistry" ref="ServiceRegistry" />
|
||||
<property name="transactionService" ref="transactionService" />
|
||||
<property name="searchMapper" ref="searchapiSearchMapper" />
|
||||
<property name="bulkMonitor" ref="holdBulkMonitor" />
|
||||
<property name="holdService" ref="HoldService" />
|
||||
<property name="capabilityService" ref="CapabilityService" />
|
||||
<property name="permissionService" ref="PermissionService" />
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="threadCount">
|
||||
<value>${rm.hold.bulk.threadCount}</value>
|
||||
</property>
|
||||
<property name="batchSize">
|
||||
<value>${rm.hold.bulk.batchSize}</value>
|
||||
</property>
|
||||
<property name="maxItems">
|
||||
<value>${rm.hold.bulk.maxItems}</value>
|
||||
</property>
|
||||
<property name="loggingInterval">
|
||||
<value>${rm.hold.bulk.logging.interval}</value>
|
||||
</property>
|
||||
<property name="itemsPerTransaction">
|
||||
<value>${rm.hold.bulk.itemsPerTransaction}</value>
|
||||
</property>
|
||||
<property name="maxParallelRequests">
|
||||
<value>${rm.hold.bulk.maxParallelRequests}</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="holdBulkMonitor" class="org.alfresco.module.org_alfresco_module_rm.bulk.hold.DefaultHoldBulkMonitor">
|
||||
<property name="holdProgressCache" ref="holdProgressCache" />
|
||||
<property name="holdProcessRegistry" ref="holdProcessRegistry" />
|
||||
<property name="bulkCancellationsCache" ref="bulkCancellationsCache" />
|
||||
</bean>
|
||||
|
||||
|
||||
<bean name="holdProgressCache" factory-bean="cacheFactory" factory-method="createCache">
|
||||
<constructor-arg value="cache.bulkHoldStatusCache" />
|
||||
</bean>
|
||||
|
||||
<bean name="holdProcessRegistry" factory-bean="cacheFactory" factory-method="createCache">
|
||||
<constructor-arg value="cache.bulkHoldRegistryCache" />
|
||||
</bean>
|
||||
|
||||
<bean name="bulkCancellationsCache" factory-bean="cacheFactory" factory-method="createCache">
|
||||
<constructor-arg value="cache.bulkCancellationsCache" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -31,6 +31,7 @@
|
||||
<property name="personService" ref="PersonService"/>
|
||||
<property name="dispositionService" ref="DispositionService"/>
|
||||
<property name="serviceRegistry" ref="ServiceRegistry"/>
|
||||
<property name="recordsManagementServiceRegistry" ref="RecordsManagementServiceRegistry"/>
|
||||
</bean>
|
||||
|
||||
<bean id="searchTypesFactory" class="org.alfresco.rm.rest.api.impl.SearchTypesFactory">
|
||||
@@ -83,6 +84,14 @@
|
||||
<property name="nodesModelFactory" ref="nodesModelFactory" />
|
||||
<property name="fileFolderService" ref="FileFolderService" />
|
||||
<property name="transactionService" ref="transactionService" />
|
||||
<property name="holdBulkService" ref="holdBulkService" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rm.rest.api.holds.HoldsBulkStatusesRelation" >
|
||||
<property name="holdBulkMonitor" ref="holdBulkMonitor" />
|
||||
<property name="holdBulkService" ref="holdBulkService" />
|
||||
<property name="apiUtils" ref="apiUtils" />
|
||||
<property name="permissionService" ref="PermissionService" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rm.rest.api.holds.HoldsChildrenRelation">
|
||||
@@ -139,6 +148,20 @@
|
||||
<property name="transactionService" ref="transactionService" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rm.rest.api.retentionschedule.RetentionScheduleRelation">
|
||||
<property name="apiUtils" ref="apiUtils" />
|
||||
<property name="nodesModelFactory" ref="nodesModelFactory" />
|
||||
<property name="dispositionService" ref="DispositionService"/>
|
||||
<property name="nodeService" ref="NodeService"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rm.rest.api.retentionschedule.RetentionScheduleActionRelation">
|
||||
<property name="apiUtils" ref="apiUtils" />
|
||||
<property name="nodesModelFactory" ref="nodesModelFactory" />
|
||||
<property name="nodeService" ref="NodeService"/>
|
||||
<property name="recordsManagementServiceRegistry" ref="RecordsManagementServiceRegistry"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rm.rest.api.recordfolders.RecordFolderEntityResource">
|
||||
<property name="apiUtils" ref="apiUtils" />
|
||||
<property name="fileFolderService" ref="FileFolderService" />
|
||||
|
@@ -41,6 +41,8 @@ services:
|
||||
-Daos.baseUrlOverwrite=http://localhost:8080/alfresco/aos
|
||||
-Dmessaging.broker.url=\"failover:(tcp://activemq:61616)?timeout=3000&jms.useCompression=true\"
|
||||
-DlocalTransform.core-aio.url=http://transform-core-aio:8090/
|
||||
-Drm.hold.bulk.maxItems=5
|
||||
-Drm.hold.bulk.batchSize=2
|
||||
"
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -155,6 +155,12 @@
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>${dependency.awaitility.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk;
|
||||
|
||||
import static java.util.concurrent.Executors.newFixedThreadPool;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.alfresco.repo.batch.BatchProcessWorkProvider;
|
||||
import org.alfresco.repo.batch.BatchProcessor;
|
||||
import org.alfresco.repo.batch.BatchProcessor.BatchProcessWorker;
|
||||
import org.alfresco.rest.api.search.impl.SearchMapper;
|
||||
import org.alfresco.rest.api.search.model.Query;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* A base class for executing bulk operations on nodes based on search query results
|
||||
*/
|
||||
public abstract class BulkBaseService<T> implements InitializingBean
|
||||
{
|
||||
private static final Log LOG = LogFactory.getLog(BulkBaseService.class);
|
||||
protected ExecutorService executorService;
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
protected SearchService searchService;
|
||||
protected TransactionService transactionService;
|
||||
protected SearchMapper searchMapper;
|
||||
protected BulkMonitor<T> bulkMonitor;
|
||||
|
||||
protected int threadCount;
|
||||
protected int batchSize;
|
||||
protected int itemsPerTransaction;
|
||||
protected int maxItems;
|
||||
protected int loggingInterval;
|
||||
protected int maxParallelRequests;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
this.searchService = serviceRegistry.getSearchService();
|
||||
this.executorService = newFixedThreadPool(maxParallelRequests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute bulk operation on node based on the search query results
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param bulkOperation bulk operation
|
||||
* @return bulk status
|
||||
*/
|
||||
public T execute(NodeRef nodeRef, BulkOperation bulkOperation)
|
||||
{
|
||||
checkPermissions(nodeRef, bulkOperation);
|
||||
|
||||
ResultSet resultSet = getTotalItems(bulkOperation.searchQuery(), maxItems);
|
||||
if (maxItems < resultSet.getNumberFound() || resultSet.hasMore())
|
||||
{
|
||||
throw new InvalidArgumentException("Too many items to process. Please refine your query.");
|
||||
}
|
||||
long totalItems = resultSet.getNumberFound();
|
||||
// Generate a random process id
|
||||
String processId = UUID.randomUUID().toString();
|
||||
|
||||
T initBulkStatus = getInitBulkStatus(processId, totalItems);
|
||||
bulkMonitor.updateBulkStatus(initBulkStatus);
|
||||
bulkMonitor.registerProcess(nodeRef, processId, bulkOperation);
|
||||
|
||||
BulkProgress bulkProgress = new BulkProgress(totalItems, processId, new AtomicBoolean(false),
|
||||
new AtomicInteger(0));
|
||||
BatchProcessWorker<NodeRef> batchProcessWorker = getWorkerProvider(nodeRef, bulkOperation, bulkProgress);
|
||||
BulkStatusUpdater bulkStatusUpdater = getBulkStatusUpdater();
|
||||
|
||||
BatchProcessor<NodeRef> batchProcessor = new BatchProcessor<>(
|
||||
processId,
|
||||
transactionService.getRetryingTransactionHelper(),
|
||||
getWorkProvider(bulkOperation, bulkStatusUpdater, bulkProgress),
|
||||
threadCount,
|
||||
itemsPerTransaction,
|
||||
bulkStatusUpdater,
|
||||
LOG,
|
||||
loggingInterval);
|
||||
|
||||
runAsyncBatchProcessor(batchProcessor, batchProcessWorker, bulkStatusUpdater);
|
||||
return initBulkStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run batch processor
|
||||
*/
|
||||
protected void runAsyncBatchProcessor(BatchProcessor<NodeRef> batchProcessor,
|
||||
BatchProcessWorker<NodeRef> batchProcessWorker, BulkStatusUpdater bulkStatusUpdater)
|
||||
{
|
||||
Runnable backgroundLogic = () -> {
|
||||
try
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("Started processing batch with name: " + batchProcessor.getProcessName());
|
||||
}
|
||||
batchProcessor.processLong(batchProcessWorker, true);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("Processing batch with name: " + batchProcessor.getProcessName() + " completed");
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LOG.error("Error processing batch with name: " + batchProcessor.getProcessName(), exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
bulkStatusUpdater.update();
|
||||
}
|
||||
};
|
||||
|
||||
executorService.submit(backgroundLogic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get initial bulk status
|
||||
*
|
||||
* @param processId process id
|
||||
* @param totalItems total items
|
||||
* @return bulk status
|
||||
*/
|
||||
protected abstract T getInitBulkStatus(String processId, long totalItems);
|
||||
|
||||
/**
|
||||
* Get bulk status updater
|
||||
*
|
||||
* @return bulk status updater
|
||||
*/
|
||||
protected abstract BulkStatusUpdater getBulkStatusUpdater();
|
||||
|
||||
/**
|
||||
* Get work provider
|
||||
*
|
||||
* @param bulkOperation bulk operation
|
||||
* @param bulkStatusUpdater bulk status updater
|
||||
* @param bulkProgress bulk progress
|
||||
* @return work provider
|
||||
*/
|
||||
protected abstract BatchProcessWorkProvider<NodeRef> getWorkProvider(BulkOperation bulkOperation,
|
||||
BulkStatusUpdater bulkStatusUpdater, BulkProgress bulkProgress);
|
||||
|
||||
/**
|
||||
* Get worker provider
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param bulkOperation bulk operation
|
||||
* @param bulkProgress bulk progress
|
||||
* @return worker provider
|
||||
*/
|
||||
protected abstract BatchProcessWorker<NodeRef> getWorkerProvider(NodeRef nodeRef, BulkOperation bulkOperation,
|
||||
BulkProgress bulkProgress);
|
||||
|
||||
/**
|
||||
* Check permissions
|
||||
*
|
||||
* @param nodeRef node reference
|
||||
* @param bulkOperation bulk operation
|
||||
*/
|
||||
protected abstract void checkPermissions(NodeRef nodeRef, BulkOperation bulkOperation);
|
||||
|
||||
protected ResultSet getTotalItems(Query searchQuery, int skipCount)
|
||||
{
|
||||
SearchParameters searchParams = new SearchParameters();
|
||||
searchMapper.setDefaults(searchParams);
|
||||
searchMapper.fromQuery(searchParams, searchQuery);
|
||||
searchParams.setSkipCount(skipCount);
|
||||
searchParams.setMaxItems(1);
|
||||
searchParams.setLimit(1);
|
||||
return searchService.query(searchParams);
|
||||
}
|
||||
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
public void setSearchMapper(SearchMapper searchMapper)
|
||||
{
|
||||
this.searchMapper = searchMapper;
|
||||
}
|
||||
|
||||
public void setBulkMonitor(BulkMonitor<T> bulkMonitor)
|
||||
{
|
||||
this.bulkMonitor = bulkMonitor;
|
||||
}
|
||||
|
||||
public void setThreadCount(int threadCount)
|
||||
{
|
||||
this.threadCount = threadCount;
|
||||
}
|
||||
|
||||
public void setBatchSize(int batchSize)
|
||||
{
|
||||
this.batchSize = batchSize;
|
||||
}
|
||||
|
||||
public void setMaxItems(int maxItems)
|
||||
{
|
||||
this.maxItems = maxItems;
|
||||
}
|
||||
|
||||
public void setLoggingInterval(int loggingInterval)
|
||||
{
|
||||
this.loggingInterval = loggingInterval;
|
||||
}
|
||||
|
||||
public void setItemsPerTransaction(int itemsPerTransaction)
|
||||
{
|
||||
this.itemsPerTransaction = itemsPerTransaction;
|
||||
}
|
||||
|
||||
public void setMaxParallelRequests(int maxParallelRequests)
|
||||
{
|
||||
this.maxParallelRequests = maxParallelRequests;
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk;
|
||||
|
||||
/**
|
||||
* An immutable POJO to represent a bulk cancellation request
|
||||
*/
|
||||
public record BulkCancellationRequest(String reason)
|
||||
{
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* An interface for monitoring the progress of a bulk operation
|
||||
*/
|
||||
public interface BulkMonitor<T>
|
||||
{
|
||||
/**
|
||||
* Update the bulk status
|
||||
*
|
||||
* @param bulkStatus the bulk status
|
||||
*/
|
||||
void updateBulkStatus(T bulkStatus);
|
||||
|
||||
/**
|
||||
* Register a process
|
||||
*
|
||||
* @param nodeRef the node reference
|
||||
* @param processId the process id
|
||||
* @param bulkOperation the bulk operation
|
||||
*/
|
||||
void registerProcess(NodeRef nodeRef, String processId, BulkOperation bulkOperation);
|
||||
|
||||
/**
|
||||
* Get the bulk status
|
||||
*
|
||||
* @param bulkStatusId the bulk status id
|
||||
* @return the bulk status
|
||||
*/
|
||||
T getBulkStatus(String bulkStatusId);
|
||||
|
||||
/**
|
||||
* Cancel a bulk operation
|
||||
*
|
||||
* @param bulkStatusId
|
||||
* @param bulkCancellationRequest
|
||||
*/
|
||||
void cancelBulkOperation(String bulkStatusId, BulkCancellationRequest bulkCancellationRequest);
|
||||
|
||||
/**
|
||||
* Check if a bulk operation is cancelled
|
||||
*
|
||||
* @param bulkStatusId
|
||||
* @return true if the bulk operation is cancelled
|
||||
*/
|
||||
boolean isCancelled(String bulkStatusId);
|
||||
|
||||
/**
|
||||
* Get the bulk cancellation request
|
||||
*
|
||||
* @param bulkStatusId
|
||||
* @return cancellation reason
|
||||
*/
|
||||
BulkCancellationRequest getBulkCancellationRequest(String bulkStatusId);
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.alfresco.rest.api.search.model.Query;
|
||||
|
||||
/**
|
||||
* An immutable POJO to represent a bulk operation
|
||||
*/
|
||||
public record BulkOperation(Query searchQuery, String operationType) implements Serializable
|
||||
{
|
||||
public BulkOperation
|
||||
{
|
||||
if (operationType == null || searchQuery == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Operation type and search query must not be null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* An immutable POJO to represent the progress of a bulk operation
|
||||
*/
|
||||
public record BulkProgress(long totalItems, String processId, AtomicBoolean cancelled, AtomicInteger currentNodeNumber)
|
||||
{
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
/**
|
||||
* An interface for updating the status of a bulk operation
|
||||
*/
|
||||
public interface BulkStatusUpdater extends ApplicationEventPublisher
|
||||
{
|
||||
/**
|
||||
* Update the bulk status
|
||||
*/
|
||||
void update();
|
||||
}
|
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkCancellationRequest;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkOperation;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
|
||||
/**
|
||||
* Default hold bulk monitor implementation
|
||||
*/
|
||||
public class DefaultHoldBulkMonitor extends AbstractLifecycleBean implements HoldBulkMonitor
|
||||
{
|
||||
protected SimpleCache<String, HoldBulkStatus> holdProgressCache;
|
||||
protected SimpleCache<String, BulkCancellationRequest> bulkCancellationsCache;
|
||||
protected SimpleCache<Pair<String, String>, HoldBulkProcessDetails> holdProcessRegistry;
|
||||
|
||||
@Override
|
||||
public void updateBulkStatus(HoldBulkStatus holdBulkStatus)
|
||||
{
|
||||
holdProgressCache.put(holdBulkStatus.bulkStatusId(), holdBulkStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerProcess(NodeRef holdRef, String processId, BulkOperation bulkOperation)
|
||||
{
|
||||
if (holdRef != null && processId != null)
|
||||
{
|
||||
holdProcessRegistry.put(new Pair<>(holdRef.getId(), processId),
|
||||
new HoldBulkProcessDetails(processId, getCurrentInstanceDetails(), bulkOperation));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HoldBulkStatus getBulkStatus(String bulkStatusId)
|
||||
{
|
||||
return holdProgressCache.get(bulkStatusId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelBulkOperation(String bulkStatusId, BulkCancellationRequest bulkCancellationRequest)
|
||||
{
|
||||
bulkCancellationsCache.put(bulkStatusId, bulkCancellationRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled(String bulkStatusId)
|
||||
{
|
||||
return bulkCancellationsCache.contains(bulkStatusId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkCancellationRequest getBulkCancellationRequest(String bulkStatusId)
|
||||
{
|
||||
return bulkCancellationsCache.get(bulkStatusId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HoldBulkStatusAndProcessDetails> getBulkStatusesWithProcessDetails(String holdId)
|
||||
{
|
||||
return holdProcessRegistry.getKeys().stream()
|
||||
.filter(holdIdAndBulkStatusId -> holdId.equals(holdIdAndBulkStatusId.getFirst()))
|
||||
.map(holdIdAndBulkStatusId -> holdProcessRegistry.get(holdIdAndBulkStatusId))
|
||||
.filter(Objects::nonNull)
|
||||
.map(createHoldBulkStatusAndProcessDetails())
|
||||
.filter(statusAndProcess -> Objects.nonNull(statusAndProcess.holdBulkStatus()))
|
||||
.sorted(sortBulkStatuses())
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HoldBulkStatusAndProcessDetails getBulkStatusWithProcessDetails(String holdId, String bulkStatusId)
|
||||
{
|
||||
return Optional.ofNullable(holdProcessRegistry.get(new Pair<>(holdId, bulkStatusId)))
|
||||
.map(createHoldBulkStatusAndProcessDetails())
|
||||
.filter(statusAndProcess -> Objects.nonNull(statusAndProcess.holdBulkStatus()))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
protected String getCurrentInstanceDetails()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Function<HoldBulkProcessDetails, HoldBulkStatusAndProcessDetails> createHoldBulkStatusAndProcessDetails()
|
||||
{
|
||||
return bulkProcessDetails -> new HoldBulkStatusAndProcessDetails(
|
||||
getBulkStatus(bulkProcessDetails.bulkStatusId()), bulkProcessDetails);
|
||||
}
|
||||
|
||||
protected static Comparator<HoldBulkStatusAndProcessDetails> sortBulkStatuses()
|
||||
{
|
||||
return Comparator.<HoldBulkStatusAndProcessDetails, Date>comparing(
|
||||
statusAndProcess -> statusAndProcess.holdBulkStatus().endTime(),
|
||||
Comparator.nullsLast(Comparator.naturalOrder()))
|
||||
.thenComparing(statusAndProcess -> statusAndProcess.holdBulkStatus().startTime(),
|
||||
Comparator.nullsLast(Comparator.naturalOrder()))
|
||||
.reversed();
|
||||
}
|
||||
|
||||
public void setHoldProgressCache(
|
||||
SimpleCache<String, HoldBulkStatus> holdProgressCache)
|
||||
{
|
||||
this.holdProgressCache = holdProgressCache;
|
||||
}
|
||||
|
||||
public void setHoldProcessRegistry(
|
||||
SimpleCache<Pair<String, String>, HoldBulkProcessDetails> holdProcessRegistry)
|
||||
{
|
||||
this.holdProcessRegistry = holdProcessRegistry;
|
||||
}
|
||||
|
||||
public void setBulkCancellationsCache(
|
||||
SimpleCache<String, BulkCancellationRequest> bulkCancellationsCache)
|
||||
{
|
||||
this.bulkCancellationsCache = bulkCancellationsCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent applicationEvent)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent applicationEvent)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkMonitor;
|
||||
|
||||
/**
|
||||
* An interface for monitoring the progress of a bulk hold operation
|
||||
*/
|
||||
public interface HoldBulkMonitor extends BulkMonitor<HoldBulkStatus>
|
||||
{
|
||||
/**
|
||||
* Get the bulk statuses with process details for a hold
|
||||
*
|
||||
* @param holdId the hold id
|
||||
* @return the bulk statuses with process details
|
||||
*/
|
||||
List<HoldBulkStatusAndProcessDetails> getBulkStatusesWithProcessDetails(String holdId);
|
||||
|
||||
/**
|
||||
* Get the bulk status with process details
|
||||
*
|
||||
* @param holdId the hold id
|
||||
* @param bulkStatusId the bulk status id
|
||||
* @return the bulk status with process details
|
||||
*/
|
||||
HoldBulkStatusAndProcessDetails getBulkStatusWithProcessDetails(String holdId, String bulkStatusId);
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkOperation;
|
||||
|
||||
/**
|
||||
* A simple immutable POJO to hold the details of a bulk process
|
||||
*/
|
||||
public record HoldBulkProcessDetails(String bulkStatusId, String creatorInstance, BulkOperation bulkOperation) implements Serializable
|
||||
{
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkCancellationRequest;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkOperation;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Interface defining a hold bulk service.
|
||||
*/
|
||||
public interface HoldBulkService
|
||||
{
|
||||
/**
|
||||
* Initiates a bulk operation on a hold.
|
||||
*
|
||||
* @param holdRef The hold reference
|
||||
* @param bulkOperation The bulk operation
|
||||
* @return The initial status of the bulk operation
|
||||
*/
|
||||
HoldBulkStatus execute(NodeRef holdRef, BulkOperation bulkOperation);
|
||||
|
||||
/**
|
||||
* Cancels a bulk operation.
|
||||
*
|
||||
* @param holdRef The hold reference
|
||||
* @param bulkStatusId The bulk status id
|
||||
* @param bulkCancellationRequest The bulk cancellation request
|
||||
*/
|
||||
void cancelBulkOperation(NodeRef holdRef, String bulkStatusId, BulkCancellationRequest bulkCancellationRequest);
|
||||
}
|
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
import static org.alfresco.model.ContentModel.PROP_NAME;
|
||||
import static org.alfresco.rm.rest.api.model.HoldBulkOperationType.ADD;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkBaseService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkCancellationRequest;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkOperation;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkProgress;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkStatusUpdater;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
|
||||
import org.alfresco.repo.batch.BatchProcessWorkProvider;
|
||||
import org.alfresco.repo.batch.BatchProcessor.BatchProcessWorker;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.rest.api.search.model.Query;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rm.rest.api.model.HoldBulkOperationType;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link HoldBulkService} interface.
|
||||
*/
|
||||
@SuppressWarnings("PMD.PreserveStackTrace")
|
||||
public class HoldBulkServiceImpl extends BulkBaseService<HoldBulkStatus> implements HoldBulkService
|
||||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HoldBulkServiceImpl.class);
|
||||
private static final String MSG_ERR_ACCESS_DENIED = "permissions.err_access_denied";
|
||||
|
||||
private HoldService holdService;
|
||||
private CapabilityService capabilityService;
|
||||
private PermissionService permissionService;
|
||||
private NodeService nodeService;
|
||||
|
||||
@Override
|
||||
protected HoldBulkStatus getInitBulkStatus(String processId, long totalItems)
|
||||
{
|
||||
return new HoldBulkStatus(processId, null, null, 0, 0, totalItems, null, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BulkStatusUpdater getBulkStatusUpdater()
|
||||
{
|
||||
return new HoldBulkStatusUpdater((HoldBulkMonitor) bulkMonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BatchProcessWorkProvider<NodeRef> getWorkProvider(BulkOperation bulkOperation,
|
||||
BulkStatusUpdater bulkStatusUpdater, BulkProgress bulkProgress)
|
||||
{
|
||||
return new AddToHoldWorkerProvider(bulkOperation, bulkStatusUpdater, bulkProgress,
|
||||
(HoldBulkMonitor) bulkMonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BatchProcessWorker<NodeRef> getWorkerProvider(NodeRef nodeRef, BulkOperation bulkOperation,
|
||||
BulkProgress bulkProgress)
|
||||
{
|
||||
try
|
||||
{
|
||||
HoldBulkOperationType holdBulkOperationType = HoldBulkOperationType.valueOf(bulkOperation.operationType()
|
||||
.toUpperCase(Locale.ENGLISH));
|
||||
return switch (holdBulkOperationType)
|
||||
{
|
||||
case ADD -> new AddToHoldWorkerBatch(nodeRef, bulkProgress);
|
||||
};
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
String errorMsg = "Unsupported action type when starting the bulk process: ";
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
LOGGER.debug("{} {}", errorMsg, bulkOperation.operationType(), e);
|
||||
}
|
||||
throw new InvalidArgumentException(errorMsg + bulkOperation.operationType());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkPermissions(NodeRef holdRef, BulkOperation bulkOperation)
|
||||
{
|
||||
if (!holdService.isHold(holdRef))
|
||||
{
|
||||
final String holdName = (String) nodeService.getProperty(holdRef, PROP_NAME);
|
||||
throw new InvalidArgumentException(I18NUtil.getMessage("rm.hold.not-hold", holdName), null);
|
||||
}
|
||||
if (ADD.name().equals(bulkOperation.operationType()) && (!AccessStatus.ALLOWED.equals(
|
||||
capabilityService.getCapabilityAccessState(holdRef, RMPermissionModel.ADD_TO_HOLD)) ||
|
||||
permissionService.hasPermission(holdRef, RMPermissionModel.FILING) == AccessStatus.DENIED))
|
||||
{
|
||||
throw new AccessDeniedException(I18NUtil.getMessage(MSG_ERR_ACCESS_DENIED));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelBulkOperation(NodeRef holdRef, String bulkStatusId, BulkCancellationRequest cancellationRequest)
|
||||
{
|
||||
if (bulkMonitor instanceof HoldBulkMonitor holdBulkMonitor)
|
||||
{
|
||||
HoldBulkStatusAndProcessDetails statusAndProcessDetails = holdBulkMonitor.getBulkStatusWithProcessDetails(
|
||||
holdRef.getId(), bulkStatusId);
|
||||
|
||||
Optional.ofNullable(statusAndProcessDetails).map(HoldBulkStatusAndProcessDetails::holdBulkProcessDetails)
|
||||
.map(HoldBulkProcessDetails::bulkOperation).ifPresent(bulkOperation -> {
|
||||
checkPermissions(holdRef, bulkOperation);
|
||||
holdBulkMonitor.cancelBulkOperation(bulkStatusId, cancellationRequest);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class AddToHoldWorkerBatch implements BatchProcessWorker<NodeRef>
|
||||
{
|
||||
private final NodeRef holdRef;
|
||||
private final String currentUser;
|
||||
private final BulkProgress bulkProgress;
|
||||
|
||||
public AddToHoldWorkerBatch(NodeRef holdRef, BulkProgress bulkProgress)
|
||||
{
|
||||
this.holdRef = holdRef;
|
||||
this.bulkProgress = bulkProgress;
|
||||
currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier(NodeRef entry)
|
||||
{
|
||||
return entry.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeProcess()
|
||||
{
|
||||
AuthenticationUtil.pushAuthentication();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(NodeRef entry) throws Throwable
|
||||
{
|
||||
if (!bulkProgress.cancelled().get())
|
||||
{
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(currentUser);
|
||||
holdService.addToHold(holdRef, entry);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterProcess()
|
||||
{
|
||||
AuthenticationUtil.popAuthentication();
|
||||
}
|
||||
}
|
||||
|
||||
private class AddToHoldWorkerProvider implements BatchProcessWorkProvider<NodeRef>
|
||||
{
|
||||
private final HoldBulkMonitor holdBulkMonitor;
|
||||
private final Query searchQuery;
|
||||
private final String currentUser;
|
||||
private final BulkProgress bulkProgress;
|
||||
private final BulkStatusUpdater bulkStatusUpdater;
|
||||
|
||||
public AddToHoldWorkerProvider(BulkOperation bulkOperation,
|
||||
BulkStatusUpdater bulkStatusUpdater, BulkProgress bulkProgress, HoldBulkMonitor holdBulkMonitor)
|
||||
{
|
||||
this.searchQuery = bulkOperation.searchQuery();
|
||||
this.bulkProgress = bulkProgress;
|
||||
this.bulkStatusUpdater = bulkStatusUpdater;
|
||||
this.holdBulkMonitor = holdBulkMonitor;
|
||||
currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalEstimatedWorkSize()
|
||||
{
|
||||
return (int) bulkProgress.totalItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalEstimatedWorkSizeLong()
|
||||
{
|
||||
return bulkProgress.totalItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<NodeRef> getNextWork()
|
||||
{
|
||||
AuthenticationUtil.pushAuthentication();
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(currentUser);
|
||||
if (holdBulkMonitor.isCancelled(bulkProgress.processId()))
|
||||
{
|
||||
bulkProgress.cancelled().set(true);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
SearchParameters searchParams = getNextPageParameters();
|
||||
ResultSet result = searchService.query(searchParams);
|
||||
if (result.getNodeRefs().isEmpty())
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
AuthenticationUtil.popAuthentication();
|
||||
if (LOGGER.isDebugEnabled())
|
||||
{
|
||||
LOGGER.debug("Processing the next work for the batch processor, skipCount={}, size={}",
|
||||
searchParams.getSkipCount(), result.getNumberFound());
|
||||
}
|
||||
bulkProgress.currentNodeNumber().addAndGet(batchSize);
|
||||
bulkStatusUpdater.update();
|
||||
return result.getNodeRefs();
|
||||
}
|
||||
|
||||
private SearchParameters getNextPageParameters()
|
||||
{
|
||||
SearchParameters searchParams = new SearchParameters();
|
||||
searchMapper.setDefaults(searchParams);
|
||||
searchMapper.fromQuery(searchParams, searchQuery);
|
||||
searchParams.setSkipCount(bulkProgress.currentNodeNumber().get());
|
||||
searchParams.setMaxItems(batchSize);
|
||||
searchParams.setLimit(batchSize);
|
||||
searchParams.addSort("@" + ContentModel.PROP_CREATED, true);
|
||||
return searchParams;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setHoldService(HoldService holdService)
|
||||
{
|
||||
this.holdService = holdService;
|
||||
}
|
||||
|
||||
public void setCapabilityService(CapabilityService capabilityService)
|
||||
{
|
||||
this.capabilityService = capabilityService;
|
||||
}
|
||||
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An immutable POJO that contains the status of a hold bulk operation
|
||||
*/
|
||||
public record HoldBulkStatus(String bulkStatusId, Date startTime, Date endTime, long processedItems, long errorsCount,
|
||||
long totalItems, String lastError, boolean isCancelled, String cancellationReason)
|
||||
implements Serializable
|
||||
{
|
||||
public enum Status
|
||||
{
|
||||
PENDING("PENDING"),
|
||||
IN_PROGRESS("IN PROGRESS"),
|
||||
DONE("DONE"),
|
||||
CANCELLED("CANCELLED");
|
||||
|
||||
private final String value;
|
||||
|
||||
Status(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
if (isCancelled)
|
||||
{
|
||||
return Status.CANCELLED.getValue();
|
||||
}
|
||||
else if (startTime == null && endTime == null)
|
||||
{
|
||||
return Status.PENDING.getValue();
|
||||
}
|
||||
else if (startTime != null && endTime == null)
|
||||
{
|
||||
return Status.IN_PROGRESS.getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Status.DONE.getValue();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
/**
|
||||
* An immutable POJO that contains the status of a hold bulk operation and the details of the process
|
||||
*/
|
||||
public record HoldBulkStatusAndProcessDetails(HoldBulkStatus holdBulkStatus,
|
||||
HoldBulkProcessDetails holdBulkProcessDetails)
|
||||
{
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkCancellationRequest;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkStatusUpdater;
|
||||
import org.alfresco.repo.batch.BatchMonitor;
|
||||
import org.alfresco.repo.batch.BatchMonitorEvent;
|
||||
|
||||
/**
|
||||
* An implementation of {@link BulkStatusUpdater} for the hold bulk operation
|
||||
*/
|
||||
public class HoldBulkStatusUpdater implements BulkStatusUpdater
|
||||
{
|
||||
private final Runnable task;
|
||||
private BatchMonitor batchMonitor;
|
||||
|
||||
public HoldBulkStatusUpdater(HoldBulkMonitor holdBulkMonitor)
|
||||
{
|
||||
this.task = () -> holdBulkMonitor.updateBulkStatus(
|
||||
new HoldBulkStatus(batchMonitor.getProcessName(),
|
||||
batchMonitor.getStartTime(),
|
||||
batchMonitor.getEndTime(),
|
||||
batchMonitor.getSuccessfullyProcessedEntriesLong() + batchMonitor.getTotalErrorsLong(),
|
||||
batchMonitor.getTotalErrorsLong(),
|
||||
batchMonitor.getTotalResultsLong(),
|
||||
batchMonitor.getLastError(),
|
||||
holdBulkMonitor.isCancelled(batchMonitor.getProcessName()),
|
||||
Optional.ofNullable(holdBulkMonitor.getBulkCancellationRequest(batchMonitor.getProcessName()))
|
||||
.map(BulkCancellationRequest::reason)
|
||||
.orElse(null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update()
|
||||
{
|
||||
if (task != null && batchMonitor != null)
|
||||
{
|
||||
task.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishEvent(Object event)
|
||||
{
|
||||
if (event instanceof BatchMonitorEvent batchMonitorEvent)
|
||||
{
|
||||
batchMonitor = batchMonitorEvent.getBatchMonitor();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk.hold;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkOperation;
|
||||
import org.alfresco.rest.api.search.model.Query;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rm.rest.api.model.HoldBulkOperation;
|
||||
import org.alfresco.rm.rest.api.model.HoldBulkOperationType;
|
||||
import org.alfresco.rm.rest.api.model.HoldBulkStatusEntry;
|
||||
|
||||
/**
|
||||
* Utility class for hold bulk operations
|
||||
*/
|
||||
@SuppressWarnings("PMD.PreserveStackTrace")
|
||||
public final class HoldBulkUtils
|
||||
{
|
||||
private HoldBulkUtils()
|
||||
{
|
||||
}
|
||||
|
||||
public static HoldBulkStatusEntry toHoldBulkStatusEntry(
|
||||
HoldBulkStatusAndProcessDetails holdBulkStatusAndProcessDetails)
|
||||
{
|
||||
HoldBulkStatus bulkStatus = holdBulkStatusAndProcessDetails.holdBulkStatus();
|
||||
BulkOperation bulkOperation = holdBulkStatusAndProcessDetails.holdBulkProcessDetails().bulkOperation();
|
||||
|
||||
try
|
||||
{
|
||||
HoldBulkOperation holdBulkOperation = new HoldBulkOperation(
|
||||
new Query(bulkOperation.searchQuery().getLanguage(),
|
||||
bulkOperation.searchQuery().getQuery(), bulkOperation.searchQuery().getUserQuery()),
|
||||
HoldBulkOperationType.valueOf(bulkOperation.operationType()));
|
||||
return new HoldBulkStatusEntry(bulkStatus.bulkStatusId(), bulkStatus.startTime(),
|
||||
bulkStatus.endTime(), bulkStatus.processedItems(), bulkStatus.errorsCount(),
|
||||
bulkStatus.totalItems(), bulkStatus.lastError(), bulkStatus.getStatus(),
|
||||
bulkStatus.cancellationReason(), holdBulkOperation);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
String errorMsg = "Unsupported action type in the bulk operation: ";
|
||||
throw new InvalidArgumentException(errorMsg + bulkOperation.operationType());
|
||||
}
|
||||
}
|
||||
}
|
@@ -59,6 +59,9 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
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.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -198,7 +201,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
/**
|
||||
* Behavior to initialize the disposition schedule of a newly filed record.
|
||||
*
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies.OnFileRecord#onFileRecord(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see RecordsManagementPolicies.OnFileRecord#onFileRecord(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
@Behaviour(kind=BehaviourKind.CLASS, type="rma:record")
|
||||
@@ -216,7 +219,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#refreshDispositionAction(NodeRef)
|
||||
* @see DispositionService#refreshDispositionAction(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public void refreshDispositionAction(NodeRef nodeRef)
|
||||
@@ -242,7 +245,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
/** ========= Disposition Property Methods ========= */
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#registerDispositionProperty(org.alfresco.module.org_alfresco_module_rm.disposition.property.DispositionProperty)
|
||||
* @see DispositionService#registerDispositionProperty(DispositionProperty)
|
||||
*/
|
||||
@Override
|
||||
public void registerDispositionProperty(DispositionProperty dispositionProperty)
|
||||
@@ -251,7 +254,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getDispositionProperties(boolean, java.lang.String)
|
||||
* @see DispositionService#getDispositionProperties(boolean, String)
|
||||
*/
|
||||
@Override
|
||||
public Collection<DispositionProperty> getDispositionProperties(boolean isRecordLevel, String dispositionAction)
|
||||
@@ -270,7 +273,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getDispositionProperties()
|
||||
* @see DispositionService#getDispositionProperties()
|
||||
*/
|
||||
@Override
|
||||
public Collection<DispositionProperty> getDispositionProperties()
|
||||
@@ -281,12 +284,11 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
/** ========= Disposition Schedule Methods ========= */
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getDispositionSchedule(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see DispositionService#getDispositionSchedule(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public DispositionSchedule getDispositionSchedule(final NodeRef nodeRef)
|
||||
{
|
||||
DispositionSchedule ds = null;
|
||||
NodeRef dsNodeRef = null;
|
||||
if (isRecord(nodeRef))
|
||||
{
|
||||
@@ -311,36 +313,33 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
if (dsNextAction != null)
|
||||
{
|
||||
final NodeRef action = dsNextAction.getNextActionNodeRef();
|
||||
if (isNotTrue((Boolean)nodeService.getProperty(action, PROP_MANUALLY_SET_AS_OF)))
|
||||
if (isNotTrue((Boolean)nodeService.getProperty(action, PROP_MANUALLY_SET_AS_OF)) && !dsNextAction.getWriteMode().equals(WriteMode.READ_ONLY))
|
||||
{
|
||||
if (!dsNextAction.getWriteMode().equals(WriteMode.READ_ONLY))
|
||||
final String dispositionActionName = dsNextAction.getNextActionName();
|
||||
final Date dispositionActionDate = dsNextAction.getNextActionDateAsOf();
|
||||
|
||||
RunAsWork<Void> runAsWork = () -> {
|
||||
nodeService.setProperty(action, PROP_DISPOSITION_AS_OF, dispositionActionDate);
|
||||
return null;
|
||||
};
|
||||
|
||||
// if the current transaction is READ ONLY set the property on the node
|
||||
// in a READ WRITE transaction
|
||||
if (AlfrescoTransactionSupport.getTransactionReadState().equals(TxnReadState.TXN_READ_ONLY))
|
||||
{
|
||||
final String dispositionActionName = dsNextAction.getNextActionName();
|
||||
final Date dispositionActionDate = dsNextAction.getNextActionDateAsOf();
|
||||
|
||||
RunAsWork<Void> runAsWork = () -> {
|
||||
nodeService.setProperty(action, PROP_DISPOSITION_AS_OF, dispositionActionDate);
|
||||
return null;
|
||||
};
|
||||
|
||||
// if the current transaction is READ ONLY set the property on the node
|
||||
// in a READ WRITE transaction
|
||||
if (AlfrescoTransactionSupport.getTransactionReadState().equals(TxnReadState.TXN_READ_ONLY))
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction((RetryingTransactionCallback<Void>) () -> {
|
||||
AuthenticationUtil.runAsSystem(runAsWork);
|
||||
return null;
|
||||
}, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction((RetryingTransactionCallback<Void>) () -> {
|
||||
AuthenticationUtil.runAsSystem(runAsWork);
|
||||
}
|
||||
return null;
|
||||
}, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuthenticationUtil.runAsSystem(runAsWork);
|
||||
}
|
||||
|
||||
if (dsNextAction.getWriteMode().equals(WriteMode.DATE_AND_NAME))
|
||||
{
|
||||
nodeService.setProperty(action, PROP_DISPOSITION_ACTION_NAME, dispositionActionName);
|
||||
}
|
||||
if (dsNextAction.getWriteMode().equals(WriteMode.DATE_AND_NAME))
|
||||
{
|
||||
nodeService.setProperty(action, PROP_DISPOSITION_ACTION_NAME, dispositionActionName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,7 +351,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
// Get the disposition instructions for the node reference provided
|
||||
dsNodeRef = getDispositionScheduleImpl(nodeRef);
|
||||
}
|
||||
|
||||
DispositionSchedule ds = null;
|
||||
if (dsNodeRef != null)
|
||||
{
|
||||
ds = new DispositionScheduleImpl(serviceRegistry, nodeService, dsNodeRef);
|
||||
@@ -382,7 +381,8 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DispositionSchedule getOriginDispositionSchedule(NodeRef nodeRef)
|
||||
{
|
||||
NodeRef parent = this.nodeService.getPrimaryParent(nodeRef).getParentRef();
|
||||
@@ -406,7 +406,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getAssociatedDispositionSchedule(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see DispositionService#getAssociatedDispositionSchedule(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public DispositionSchedule getAssociatedDispositionSchedule(NodeRef nodeRef)
|
||||
@@ -437,7 +437,6 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
*/
|
||||
private NodeRef getAssociatedDispositionScheduleImpl(NodeRef nodeRef)
|
||||
{
|
||||
NodeRef result = null;
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
// Make sure we are dealing with an RM node
|
||||
@@ -445,6 +444,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Can not find the associated retention schedule for a non records management component. (nodeRef=" + nodeRef.toString() + ")");
|
||||
}
|
||||
NodeRef result = null;
|
||||
if (getInternalNodeService().hasAspect(nodeRef, ASPECT_SCHEDULED))
|
||||
{
|
||||
List<ChildAssociationRef> childAssocs = getInternalNodeService().getChildAssocs(nodeRef, ASSOC_DISPOSITION_SCHEDULE, RegexQNamePattern.MATCH_ALL);
|
||||
@@ -459,7 +459,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getAssociatedRecordsManagementContainer(org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule)
|
||||
* @see DispositionService#getAssociatedRecordsManagementContainer(DispositionSchedule)
|
||||
*/
|
||||
@Override
|
||||
public NodeRef getAssociatedRecordsManagementContainer(DispositionSchedule dispositionSchedule)
|
||||
@@ -477,12 +477,9 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
// TODO in the future we should be able to support disposition schedule reuse, but for now just warn that
|
||||
// only the first disposition schedule will be considered
|
||||
if (LOGGER.isWarnEnabled())
|
||||
{
|
||||
LOGGER.warn("Retention schedule has more than one associated records management container. " +
|
||||
"This is not currently supported so only the first container will be considered. " +
|
||||
"(dispositionScheduleNodeRef=" + dispositionSchedule.getNodeRef().toString() + ")");
|
||||
}
|
||||
LOGGER.atWarn().log("Retention schedule has more than one associated records management container. " +
|
||||
"This is not currently supported so only the first container will be considered. " +
|
||||
"(dispositionScheduleNodeRef={})", dispositionSchedule.getNodeRef());
|
||||
}
|
||||
|
||||
// Get the container reference
|
||||
@@ -495,7 +492,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#hasDisposableItems(org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule)
|
||||
* @see DispositionService#hasDisposableItems(DispositionSchedule)
|
||||
*/
|
||||
@Override
|
||||
public boolean hasDisposableItems(DispositionSchedule dispositionSchdule)
|
||||
@@ -537,19 +534,16 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (filePlanService.isRecordCategory(item) && getAssociatedDispositionScheduleImpl(item) == null)
|
||||
else if (filePlanService.isRecordCategory(item) && getAssociatedDispositionScheduleImpl(item) == null && hasDisposableItemsImpl(isRecordLevelDisposition, item))
|
||||
{
|
||||
if (hasDisposableItemsImpl(isRecordLevelDisposition, item));
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getDisposableItems(org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule)
|
||||
* @see DispositionService#getDisposableItems(DispositionSchedule)
|
||||
*/
|
||||
@Override
|
||||
public List<NodeRef> getDisposableItems(DispositionSchedule dispositionSchedule)
|
||||
@@ -564,7 +558,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#isDisposableItem(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see DispositionService#isDisposableItem(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean isDisposableItem(NodeRef nodeRef)
|
||||
@@ -604,20 +598,18 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#createDispositionSchedule(org.alfresco.service.cmr.repository.NodeRef, java.util.Map)
|
||||
* @see DispositionService#createDispositionSchedule(NodeRef, Map)
|
||||
*/
|
||||
@Override
|
||||
public DispositionSchedule createDispositionSchedule(NodeRef nodeRef, Map<QName, Serializable> props)
|
||||
{
|
||||
NodeRef dsNodeRef = null;
|
||||
|
||||
// Check mandatory parameters
|
||||
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||
|
||||
// Check exists
|
||||
if (!nodeService.exists(nodeRef))
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to create retention schedule, because node does not exist. (nodeRef=" + nodeRef.toString() + ")");
|
||||
throw new EntityNotFoundException(nodeRef.getId());
|
||||
}
|
||||
|
||||
// Check is sub-type of rm:recordCategory
|
||||
@@ -625,10 +617,12 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
if (!TYPE_RECORD_CATEGORY.equals(nodeRefType) &&
|
||||
!dictionaryService.isSubClass(nodeRefType, TYPE_RECORD_CATEGORY))
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to create retention schedule on a node that is not a records management container.");
|
||||
throw new InvalidArgumentException("The given id:'" + nodeRef.getId() + "' (nodeType:" + nodeRef
|
||||
+ ") is not valid. Expected nodeType is:" + TYPE_RECORD_CATEGORY);
|
||||
}
|
||||
|
||||
behaviourFilter.disableBehaviour(nodeRef, ASPECT_SCHEDULED);
|
||||
NodeRef dsNodeRef = null;
|
||||
try
|
||||
{
|
||||
// Add the schedules aspect if required
|
||||
@@ -662,7 +656,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
else
|
||||
{
|
||||
// Error since the node already has a disposition schedule set
|
||||
throw new AlfrescoRuntimeException("Unable to create retention schedule on node that already has a retention schedule.");
|
||||
throw new ConstraintViolatedException("Unable to create retention schedule on node that already has a retention schedule.");
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -686,7 +680,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
// make sure at least a name has been defined
|
||||
String name = (String)actionDefinitionParams.get(PROP_DISPOSITION_ACTION_NAME);
|
||||
if (name == null || name.length() == 0)
|
||||
if (name == null || name.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("'name' parameter is mandatory when creating a disposition action definition");
|
||||
}
|
||||
@@ -695,10 +689,10 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
|
||||
// create the child association from the schedule to the action definition
|
||||
NodeRef actionNodeRef = this.nodeService.createNode(schedule.getNodeRef(),
|
||||
RecordsManagementModel.ASSOC_DISPOSITION_ACTION_DEFINITIONS,
|
||||
ASSOC_DISPOSITION_ACTION_DEFINITIONS,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
|
||||
QName.createValidLocalName(name)),
|
||||
RecordsManagementModel.TYPE_DISPOSITION_ACTION_DEFINITION, actionDefinitionParams).getChildRef();
|
||||
TYPE_DISPOSITION_ACTION_DEFINITION, actionDefinitionParams).getChildRef();
|
||||
|
||||
// get the updated disposition schedule and retrieve the new action definition
|
||||
NodeRef scheduleParent = this.nodeService.getPrimaryParent(schedule.getNodeRef()).getParentRef();
|
||||
@@ -707,7 +701,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#removeDispositionActionDefinition(org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule, org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition)
|
||||
* @see DispositionService#removeDispositionActionDefinition(DispositionSchedule, DispositionActionDefinition)
|
||||
*/
|
||||
@Override
|
||||
public void removeDispositionActionDefinition(DispositionSchedule schedule, DispositionActionDefinition actionDefinition)
|
||||
@@ -777,16 +771,12 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
|
||||
DispositionAction da;
|
||||
// check if current transaction is a READ ONLY one and if true create the node in a READ WRITE transaction
|
||||
if (AlfrescoTransactionSupport.getTransactionReadState().equals(TxnReadState.TXN_READ_ONLY))
|
||||
{
|
||||
da =
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<DispositionAction>()
|
||||
{
|
||||
public DispositionAction execute() throws Throwable
|
||||
{
|
||||
return createDispositionAction(nodeRef, props);
|
||||
}
|
||||
}, false, true);
|
||||
if (AlfrescoTransactionSupport.getTransactionReadState().equals(TxnReadState.TXN_READ_ONLY)) {
|
||||
da = transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
() -> createDispositionAction(nodeRef, props),
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -836,13 +826,13 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
Period period = dispositionActionDefinition.getPeriod();
|
||||
if (period != null)
|
||||
{
|
||||
Date contextDate = null;
|
||||
Date contextDate;
|
||||
|
||||
// Get the period properties value
|
||||
QName periodProperty = dispositionActionDefinition.getPeriodProperty();
|
||||
if (periodProperty != null)
|
||||
{
|
||||
if (RecordsManagementModel.PROP_DISPOSITION_AS_OF.equals(periodProperty))
|
||||
if (PROP_DISPOSITION_AS_OF.equals(periodProperty))
|
||||
{
|
||||
DispositionAction lastCompletedDispositionAction = getLastCompletedDispostionAction(nodeRef);
|
||||
if (lastCompletedDispositionAction != null)
|
||||
@@ -886,7 +876,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#isNextDispositionActionEligible(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see DispositionService#isNextDispositionActionEligible(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean isNextDispositionActionEligible(NodeRef nodeRef)
|
||||
@@ -940,7 +930,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
NodeRef eventExecution = assoc.getChildRef();
|
||||
Boolean isCompleteValue = (Boolean) getInternalNodeService().getProperty(eventExecution, PROP_EVENT_EXECUTION_COMPLETE);
|
||||
boolean isComplete = false;
|
||||
boolean isComplete;
|
||||
if (isCompleteValue != null)
|
||||
{
|
||||
isComplete = isCompleteValue.booleanValue();
|
||||
@@ -987,7 +977,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getNextDispositionAction(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see DispositionService#getNextDispositionAction(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public DispositionAction getNextDispositionAction(NodeRef nodeRef)
|
||||
@@ -1006,7 +996,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
/** ========= Disposition Action History Methods ========= */
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getCompletedDispositionActions(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see DispositionService#getCompletedDispositionActions(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public List<DispositionAction> getCompletedDispositionActions(NodeRef nodeRef)
|
||||
@@ -1022,7 +1012,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#getLastCompletedDispostionAction(org.alfresco.service.cmr.repository.NodeRef)
|
||||
* @see DispositionService#getLastCompletedDispostionAction(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public DispositionAction getLastCompletedDispostionAction(NodeRef nodeRef)
|
||||
@@ -1038,7 +1028,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#isDisposableItemCutoff(NodeRef)
|
||||
* @see DispositionService#isDisposableItemCutoff(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public boolean isDisposableItemCutoff(NodeRef nodeRef)
|
||||
@@ -1048,7 +1038,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#updateNextDispositionAction(NodeRef)
|
||||
* @see DispositionService#updateNextDispositionAction(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public void updateNextDispositionAction(final NodeRef nodeRef)
|
||||
@@ -1058,7 +1048,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
RunAsWork<Void> runAsWork = new RunAsWork<Void>()
|
||||
{
|
||||
/**
|
||||
* @see org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork#doWork()
|
||||
* @see RunAsWork#doWork()
|
||||
*/
|
||||
@Override
|
||||
public Void doWork()
|
||||
@@ -1077,7 +1067,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#updateNextDispositionAction(NodeRef)
|
||||
* @see DispositionService#updateNextDispositionAction(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public void updateNextDispositionAction(final NodeRef nodeRef, final DispositionSchedule dispositionSchedule)
|
||||
@@ -1087,7 +1077,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
RunAsWork<Void> runAsWork = new RunAsWork<Void>()
|
||||
{
|
||||
/**
|
||||
* @see org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork#doWork()
|
||||
* @see RunAsWork#doWork()
|
||||
*/
|
||||
@Override
|
||||
public Void doWork()
|
||||
@@ -1113,16 +1103,13 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
List<DispositionActionDefinition> dispositionActionDefinitions = dispositionSchedule.getDispositionActionDefinitions();
|
||||
DispositionActionDefinition currentDispositionActionDefinition = null;
|
||||
DispositionActionDefinition currentDispositionActionDefinition;
|
||||
DispositionActionDefinition nextDispositionActionDefinition = null;
|
||||
|
||||
if (currentDispositionAction == null)
|
||||
if (currentDispositionAction == null && !dispositionActionDefinitions.isEmpty())
|
||||
{
|
||||
if (!dispositionActionDefinitions.isEmpty())
|
||||
{
|
||||
// The next disposition action is the first action
|
||||
nextDispositionActionDefinition = dispositionActionDefinitions.get(0);
|
||||
}
|
||||
// The next disposition action is the first action
|
||||
nextDispositionActionDefinition = dispositionActionDefinitions.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1167,7 +1154,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#cutoffDisposableItem(NodeRef)
|
||||
* @see DispositionService#cutoffDisposableItem(NodeRef)
|
||||
*/
|
||||
@Override
|
||||
public void cutoffDisposableItem(final NodeRef nodeRef)
|
||||
@@ -1205,6 +1192,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
// runAs system so that we can close a record that has already been cutoff
|
||||
authenticationUtil.runAsSystem(new RunAsWork<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void doWork() throws Exception
|
||||
{
|
||||
recordFolderService.closeRecordFolder(nodeRef);
|
||||
@@ -1224,6 +1212,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getDispositionActionDate(NodeRef record, NodeRef dispositionSchedule, String dispositionActionName)
|
||||
{
|
||||
DispositionSchedule ds = new DispositionScheduleImpl(serviceRegistry, nodeService, dispositionSchedule);
|
||||
@@ -1243,7 +1232,8 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void recalculateNextDispositionStep(NodeRef record)
|
||||
{
|
||||
List<NodeRef> recordFolders = recordFolderService.getRecordFolders(record);
|
||||
@@ -1384,14 +1374,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
Date calculatedDate = (nextDispositionActionDate != null ? nextDispositionActionDate : maxDate);
|
||||
|
||||
// We only need to update the date if the current one is too early.
|
||||
if (recordDate.before(calculatedDate))
|
||||
{
|
||||
return WriteMode.DATE_ONLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return WriteMode.READ_ONLY;
|
||||
}
|
||||
return recordDate.before(calculatedDate) ? WriteMode.DATE_ONLY : WriteMode.READ_ONLY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1414,7 +1397,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
DispositionSchedule ds = new DispositionScheduleImpl(serviceRegistry, nodeService, folderDS);
|
||||
List<DispositionActionDefinition> dispositionActionDefinitions = ds.getDispositionActionDefinitions();
|
||||
|
||||
if (dispositionActionDefinitions != null && dispositionActionDefinitions.size() > 0)
|
||||
if (dispositionActionDefinitions != null && !dispositionActionDefinitions.isEmpty())
|
||||
{
|
||||
DispositionActionDefinition firstDispositionActionDef = dispositionActionDefinitions.get(0);
|
||||
dispositionNodeRef = folderDS;
|
||||
|
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.holds;
|
||||
|
||||
import static org.alfresco.module.org_alfresco_module_rm.util.RMParameterCheck.checkNotBlank;
|
||||
import static org.alfresco.util.ParameterCheck.mandatory;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkCancellationRequest;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkMonitor;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkStatusAndProcessDetails;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkUtils;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.rest.framework.Operation;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
|
||||
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.Parameters;
|
||||
import org.alfresco.rest.framework.webscripts.WithResponse;
|
||||
import org.alfresco.rm.rest.api.impl.FilePlanComponentsApiUtils;
|
||||
import org.alfresco.rm.rest.api.model.BulkCancellationEntry;
|
||||
import org.alfresco.rm.rest.api.model.HoldBulkStatusEntry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
@RelationshipResource(name = "bulk-statuses", entityResource = HoldsEntityResource.class, title = "Bulk statuses of a hold")
|
||||
public class HoldsBulkStatusesRelation
|
||||
implements RelationshipResourceAction.Read<HoldBulkStatusEntry>,
|
||||
RelationshipResourceAction.ReadById<HoldBulkStatusEntry>
|
||||
{
|
||||
private HoldBulkMonitor holdBulkMonitor;
|
||||
private HoldBulkService holdBulkService;
|
||||
private FilePlanComponentsApiUtils apiUtils;
|
||||
private PermissionService permissionService;
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<HoldBulkStatusEntry> readAll(String holdId, Parameters parameters)
|
||||
{
|
||||
// validate parameters
|
||||
checkNotBlank("holdId", holdId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef holdRef = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
|
||||
checkReadPermissions(holdRef);
|
||||
|
||||
List<HoldBulkStatusAndProcessDetails> statuses = holdBulkMonitor.getBulkStatusesWithProcessDetails(holdId);
|
||||
List<HoldBulkStatusEntry> page = statuses.stream()
|
||||
.map(HoldBulkUtils::toHoldBulkStatusEntry)
|
||||
.skip(parameters.getPaging().getSkipCount())
|
||||
.limit(parameters.getPaging().getMaxItems())
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
|
||||
int totalItems = statuses.size();
|
||||
boolean hasMore = parameters.getPaging().getSkipCount() + parameters.getPaging().getMaxItems() < totalItems;
|
||||
return CollectionWithPagingInfo.asPaged(parameters.getPaging(), page, hasMore, totalItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HoldBulkStatusEntry readById(String holdId, String bulkStatusId, Parameters parameters)
|
||||
throws RelationshipResourceNotFoundException
|
||||
{
|
||||
checkNotBlank("holdId", holdId);
|
||||
checkNotBlank("bulkStatusId", bulkStatusId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef holdRef = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
|
||||
checkReadPermissions(holdRef);
|
||||
|
||||
return Optional.ofNullable(holdBulkMonitor.getBulkStatusWithProcessDetails(holdId, bulkStatusId))
|
||||
.map(HoldBulkUtils::toHoldBulkStatusEntry)
|
||||
.orElseThrow(() -> new EntityNotFoundException(bulkStatusId));
|
||||
}
|
||||
|
||||
@Operation("cancel")
|
||||
@WebApiDescription(title = "Cancel a bulk operation",
|
||||
successStatus = HttpServletResponse.SC_OK)
|
||||
public void cancelBulkOperation(String holdId, String bulkStatusId, BulkCancellationEntry bulkCancellationEntry,
|
||||
Parameters parameters,
|
||||
WithResponse withResponse)
|
||||
{
|
||||
checkNotBlank("holdId", holdId);
|
||||
checkNotBlank("bulkStatusId", bulkStatusId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef holdRef = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
|
||||
checkReadPermissions(holdRef);
|
||||
|
||||
if (holdBulkMonitor.getBulkStatus(bulkStatusId) == null)
|
||||
{
|
||||
throw new NotFoundException("Bulk status not found");
|
||||
}
|
||||
|
||||
holdBulkService.cancelBulkOperation(holdRef, bulkStatusId, new BulkCancellationRequest(bulkCancellationEntry.reason()));
|
||||
}
|
||||
|
||||
private void checkReadPermissions(NodeRef holdRef)
|
||||
{
|
||||
if (permissionService.hasReadPermission(holdRef) == AccessStatus.DENIED)
|
||||
{
|
||||
throw new PermissionDeniedException(I18NUtil.getMessage("permissions.err_access_denied"));
|
||||
}
|
||||
}
|
||||
|
||||
public void setHoldBulkMonitor(HoldBulkMonitor holdBulkMonitor)
|
||||
{
|
||||
this.holdBulkMonitor = holdBulkMonitor;
|
||||
}
|
||||
|
||||
public void setApiUtils(FilePlanComponentsApiUtils apiUtils)
|
||||
{
|
||||
this.apiUtils = apiUtils;
|
||||
}
|
||||
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public void setHoldBulkService(HoldBulkService holdBulkService)
|
||||
{
|
||||
this.holdBulkService = holdBulkService;
|
||||
}
|
||||
}
|
@@ -30,6 +30,8 @@ import static org.alfresco.module.org_alfresco_module_rm.util.RMParameterCheck.c
|
||||
import static org.alfresco.util.ParameterCheck.mandatory;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkOperation;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
@@ -42,6 +44,9 @@ import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.framework.webscripts.WithResponse;
|
||||
import org.alfresco.rm.rest.api.impl.ApiNodesModelFactory;
|
||||
import org.alfresco.rm.rest.api.impl.FilePlanComponentsApiUtils;
|
||||
import org.alfresco.rm.rest.api.model.HoldBulkOperation;
|
||||
import org.alfresco.rm.rest.api.model.HoldBulkOperationEntry;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkStatus;
|
||||
import org.alfresco.rm.rest.api.model.HoldDeletionReason;
|
||||
import org.alfresco.rm.rest.api.model.HoldModel;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
@@ -68,6 +73,7 @@ public class HoldsEntityResource implements
|
||||
private ApiNodesModelFactory nodesModelFactory;
|
||||
private HoldService holdService;
|
||||
private TransactionService transactionService;
|
||||
private HoldBulkService holdBulkService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
@@ -157,6 +163,23 @@ public class HoldsEntityResource implements
|
||||
return reason;
|
||||
}
|
||||
|
||||
@Operation("bulk")
|
||||
@WebApiDescription(title = "Start the hold bulk operation",
|
||||
successStatus = HttpServletResponse.SC_ACCEPTED)
|
||||
public HoldBulkOperationEntry bulk(String holdId, HoldBulkOperation holdBulkOperation, Parameters parameters,
|
||||
WithResponse withResponse)
|
||||
{
|
||||
// validate parameters
|
||||
checkNotBlank("holdId", holdId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef parentNodeRef = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
|
||||
HoldBulkStatus holdBulkStatus = holdBulkService.execute(parentNodeRef,
|
||||
new BulkOperation(holdBulkOperation.query(), holdBulkOperation.op().name()));
|
||||
return new HoldBulkOperationEntry(holdBulkStatus.bulkStatusId(), holdBulkStatus.totalItems());
|
||||
}
|
||||
|
||||
public void setApiUtils(FilePlanComponentsApiUtils apiUtils)
|
||||
{
|
||||
this.apiUtils = apiUtils;
|
||||
@@ -181,4 +204,9 @@ public class HoldsEntityResource implements
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
public void setHoldBulkService(HoldBulkService holdBulkService)
|
||||
{
|
||||
this.holdBulkService = holdBulkService;
|
||||
}
|
||||
}
|
||||
|
@@ -34,10 +34,16 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinitionImpl;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEvent;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
import org.alfresco.rest.api.model.AssocChild;
|
||||
@@ -53,6 +59,8 @@ import org.alfresco.rm.rest.api.model.Record;
|
||||
import org.alfresco.rm.rest.api.model.RecordCategory;
|
||||
import org.alfresco.rm.rest.api.model.RecordCategoryChild;
|
||||
import org.alfresco.rm.rest.api.model.RecordFolder;
|
||||
import org.alfresco.rm.rest.api.model.RetentionPeriod;
|
||||
import org.alfresco.rm.rest.api.model.RetentionSteps;
|
||||
import org.alfresco.rm.rest.api.model.Transfer;
|
||||
import org.alfresco.rm.rest.api.model.TransferChild;
|
||||
import org.alfresco.rm.rest.api.model.TransferContainer;
|
||||
@@ -61,6 +69,8 @@ import org.alfresco.rm.rest.api.model.UnfiledContainer;
|
||||
import org.alfresco.rm.rest.api.model.UnfiledContainerChild;
|
||||
import org.alfresco.rm.rest.api.model.UnfiledRecordFolder;
|
||||
import org.alfresco.rm.rest.api.model.UnfiledRecordFolderChild;
|
||||
import org.alfresco.rm.rest.api.model.RetentionSchedule;
|
||||
import org.alfresco.rm.rest.api.model.RetentionScheduleActionDefinition;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
@@ -70,6 +80,9 @@ import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Utility class containing Alfresco and RM java services required by the API
|
||||
@@ -81,6 +94,9 @@ import org.alfresco.service.namespace.QName;
|
||||
public class ApiNodesModelFactory
|
||||
{
|
||||
|
||||
/** Logger */
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApiNodesModelFactory.class);
|
||||
|
||||
// excluded namespaces (aspects, properties, assoc types)
|
||||
public static final List<String> EXCLUDED_NS = Arrays.asList(NamespaceService.SYSTEM_MODEL_1_0_URI);
|
||||
|
||||
@@ -102,6 +118,7 @@ public class ApiNodesModelFactory
|
||||
private PersonService personService;
|
||||
private DispositionService dispositionService;
|
||||
private ServiceRegistry serviceRegistry;
|
||||
private RecordsManagementServiceRegistry services;
|
||||
|
||||
public NodeService getNodeService()
|
||||
{
|
||||
@@ -153,6 +170,11 @@ public class ApiNodesModelFactory
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
public void setRecordsManagementServiceRegistry(RecordsManagementServiceRegistry services)
|
||||
{
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that sets the basic information for most of the node types.
|
||||
*
|
||||
@@ -504,15 +526,15 @@ public class ApiNodesModelFactory
|
||||
}
|
||||
if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(info.getType()))
|
||||
{
|
||||
if((!isMinimalInfo && propertyFilter.isAllowed(RecordCategoryChild.PARAM_IS_RECORD_FOLDER)) || (isMinimalInfo && includeParam.contains(RecordCategoryChild.PARAM_IS_RECORD_FOLDER)))
|
||||
if (isRecordFolder(isMinimalInfo, propertyFilter, includeParam))
|
||||
{
|
||||
recordCategoryChild.setIsRecordFolder(true);
|
||||
}
|
||||
if((!isMinimalInfo && propertyFilter.isAllowed(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY)) || (isMinimalInfo && includeParam.contains(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY)))
|
||||
if (isRecordCategory(isMinimalInfo, propertyFilter, includeParam))
|
||||
{
|
||||
recordCategoryChild.setIsRecordCategory(false);
|
||||
}
|
||||
if((!isMinimalInfo && propertyFilter.isAllowed(RMNode.PARAM_IS_CLOSED)) || (isMinimalInfo && includeParam.contains(RMNode.PARAM_IS_CLOSED)))
|
||||
if (isRecordCategoryChildClosed(isMinimalInfo, propertyFilter, includeParam))
|
||||
{
|
||||
recordCategoryChild.setIsClosed((Boolean) nodeService.getProperty(info.getNodeRef(), RecordsManagementModel.PROP_IS_CLOSED));
|
||||
}
|
||||
@@ -523,11 +545,11 @@ public class ApiNodesModelFactory
|
||||
}
|
||||
else
|
||||
{
|
||||
if((!isMinimalInfo && propertyFilter.isAllowed(RecordCategoryChild.PARAM_IS_RECORD_FOLDER)) || (isMinimalInfo && includeParam.contains(RecordCategoryChild.PARAM_IS_RECORD_FOLDER)))
|
||||
if (isRecordFolder(isMinimalInfo, propertyFilter, includeParam))
|
||||
{
|
||||
recordCategoryChild.setIsRecordFolder(false);
|
||||
}
|
||||
if((!isMinimalInfo && propertyFilter.isAllowed(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY)) || (isMinimalInfo && includeParam.contains(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY)))
|
||||
if (isRecordCategory(isMinimalInfo, propertyFilter, includeParam))
|
||||
{
|
||||
recordCategoryChild.setIsRecordCategory(true);
|
||||
}
|
||||
@@ -536,13 +558,28 @@ public class ApiNodesModelFactory
|
||||
DispositionSchedule ds = dispositionService.getDispositionSchedule(info.getNodeRef());
|
||||
recordCategoryChild.setHasRetentionSchedule(ds != null);
|
||||
}
|
||||
if((!isMinimalInfo && propertyFilter.isAllowed(RMNode.PARAM_IS_CLOSED)) || (isMinimalInfo && includeParam.contains(RMNode.PARAM_IS_CLOSED)))
|
||||
if (isRecordCategoryChildClosed(isMinimalInfo, propertyFilter, includeParam))
|
||||
{
|
||||
recordCategoryChild.setIsClosed(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRecordCategoryChildClosed(boolean isMinimalInfo, BeanPropertiesFilter propertyFilter, List<String> includeParam)
|
||||
{
|
||||
return (!isMinimalInfo && propertyFilter.isAllowed(RMNode.PARAM_IS_CLOSED)) || (isMinimalInfo && includeParam.contains(RMNode.PARAM_IS_CLOSED));
|
||||
}
|
||||
|
||||
private boolean isRecordCategory(boolean isMinimalInfo, BeanPropertiesFilter propertyFilter, List<String> includeParam)
|
||||
{
|
||||
return (!isMinimalInfo && propertyFilter.isAllowed(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY)) || (isMinimalInfo && includeParam.contains(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY));
|
||||
}
|
||||
|
||||
private boolean isRecordFolder(boolean isMinimalInfo, BeanPropertiesFilter propertyFilter, List<String> includeParam)
|
||||
{
|
||||
return (!isMinimalInfo && propertyFilter.isAllowed(RecordCategoryChild.PARAM_IS_RECORD_FOLDER)) || (isMinimalInfo && includeParam.contains(RecordCategoryChild.PARAM_IS_RECORD_FOLDER));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility method that maps record specific fields
|
||||
@@ -565,7 +602,8 @@ public class ApiNodesModelFactory
|
||||
{
|
||||
Serializable val = info.getProperties().get(ContentModel.PROP_CONTENT);
|
||||
|
||||
if ((val != null) && (val instanceof ContentData)) {
|
||||
if (val instanceof ContentData)
|
||||
{
|
||||
ContentData cd = (ContentData)val;
|
||||
String mimeType = cd.getMimetype();
|
||||
String mimeTypeName = serviceRegistry.getMimetypeService().getDisplaysByMimetype().get(mimeType);
|
||||
@@ -891,4 +929,238 @@ public class ApiNodesModelFactory
|
||||
mapAssociations(record, info, parameters.getInclude());
|
||||
return record;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that sets the information for the retention schedule type.
|
||||
* @param dispositionSchedule
|
||||
* @return RetentionSchedule
|
||||
*/
|
||||
public RetentionSchedule mapRetentionScheduleData(DispositionSchedule dispositionSchedule)
|
||||
{
|
||||
RetentionSchedule retentionSchedule = new RetentionSchedule();
|
||||
retentionSchedule.setId(dispositionSchedule.getNodeRef().getId());
|
||||
if (dispositionSchedule.getNodeRef() != null) {
|
||||
NodeRef parent = this.nodeService.getPrimaryParent(dispositionSchedule.getNodeRef()).getParentRef();
|
||||
retentionSchedule.setParentId(parent.getId());
|
||||
}
|
||||
retentionSchedule.setInstructions(dispositionSchedule.getDispositionInstructions());
|
||||
retentionSchedule.setAuthority(dispositionSchedule.getDispositionAuthority());
|
||||
retentionSchedule.setIsRecordLevel(dispositionSchedule.isRecordLevelDisposition());
|
||||
|
||||
boolean unpublishedUpdates = dispositionSchedule.getDispositionActionDefinitions().stream()
|
||||
.map(DispositionActionDefinition::getNodeRef)
|
||||
.anyMatch(actionDefNodeRef -> nodeService.hasAspect(actionDefNodeRef, RecordsManagementModel.ASPECT_UNPUBLISHED_UPDATE));
|
||||
retentionSchedule.setUnpublishedUpdates(unpublishedUpdates);
|
||||
return retentionSchedule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that sets the information for the retention schedule action definition type.
|
||||
* @param dispositionActionDefinition
|
||||
* @return RetentionScheduleActionDefinition
|
||||
*/
|
||||
public RetentionScheduleActionDefinition mapRetentionScheduleActionDefData(DispositionActionDefinition dispositionActionDefinition)
|
||||
{
|
||||
RetentionScheduleActionDefinition retentionScheduleActionDefinition = new RetentionScheduleActionDefinition();
|
||||
// Mapping basic properties
|
||||
mapRetentionActionProperties(dispositionActionDefinition, retentionScheduleActionDefinition);
|
||||
// Mapping period and period amount
|
||||
mapPeriodProperties(dispositionActionDefinition, retentionScheduleActionDefinition);
|
||||
// Mapping events properties
|
||||
mapEventsProperties(dispositionActionDefinition, retentionScheduleActionDefinition);
|
||||
return retentionScheduleActionDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that sets core information for the retention schedule action definition type.
|
||||
* @param dispositionActionDefinition
|
||||
* @param retentionScheduleActionDefinition
|
||||
*/
|
||||
private void mapRetentionActionProperties(DispositionActionDefinition dispositionActionDefinition, RetentionScheduleActionDefinition retentionScheduleActionDefinition)
|
||||
{
|
||||
retentionScheduleActionDefinition.setId(dispositionActionDefinition.getId());
|
||||
retentionScheduleActionDefinition.setName(dispositionActionDefinition.getName());
|
||||
retentionScheduleActionDefinition.setDescription(dispositionActionDefinition.getDescription());
|
||||
retentionScheduleActionDefinition.setEligibleOnFirstCompleteEvent(dispositionActionDefinition.eligibleOnFirstCompleteEvent());
|
||||
if (nodeService.getProperty(dispositionActionDefinition.getNodeRef(), RecordsManagementModel.PROP_COMBINE_DISPOSITION_STEP_CONDITIONS) != null)
|
||||
{
|
||||
retentionScheduleActionDefinition.setCombineRetentionStepConditions((Boolean) nodeService.getProperty(dispositionActionDefinition.getNodeRef(), RecordsManagementModel.PROP_COMBINE_DISPOSITION_STEP_CONDITIONS));
|
||||
}
|
||||
retentionScheduleActionDefinition.setLocation(dispositionActionDefinition.getLocation());
|
||||
if (dispositionActionDefinition.getGhostOnDestroy() != null)
|
||||
{
|
||||
retentionScheduleActionDefinition.setRetainRecordMetadataAfterDestruction(dispositionActionDefinition.getGhostOnDestroy().equals("ghost"));
|
||||
}
|
||||
retentionScheduleActionDefinition.setIndex(dispositionActionDefinition.getIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that sets the period-related information for the retention schedule action definition type.
|
||||
* @param dispositionActionDefinition
|
||||
* @param retentionScheduleActionDefinition
|
||||
*/
|
||||
private void mapPeriodProperties(DispositionActionDefinition dispositionActionDefinition, RetentionScheduleActionDefinition retentionScheduleActionDefinition)
|
||||
{
|
||||
if (dispositionActionDefinition.getPeriodProperty() != null)
|
||||
{
|
||||
retentionScheduleActionDefinition.setPeriodProperty(dispositionActionDefinition.getPeriodProperty().toPrefixString(namespaceService));
|
||||
}
|
||||
|
||||
String period = dispositionActionDefinition.getPeriod().toString();
|
||||
if (!period.isEmpty())
|
||||
{
|
||||
// In rest api we are splitting `period` property into `period` and `periodAmount`.
|
||||
// so we need to split the period into two properties.
|
||||
// ex. period -> 'month|10' so the split properties would be like below
|
||||
// period -> 'month'
|
||||
// periodAmount -> 10
|
||||
String[] periodArray = period.split("\\|");
|
||||
|
||||
if (periodArray.length > 0)
|
||||
{
|
||||
retentionScheduleActionDefinition.setPeriod(periodArray[0]);
|
||||
}
|
||||
|
||||
if (periodArray.length > 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
retentionScheduleActionDefinition.setPeriodAmount(Integer.parseInt(periodArray[1]));
|
||||
}
|
||||
catch (NumberFormatException numberFormatException)
|
||||
{
|
||||
LOGGER.error("Error parsing period amount: {}{}", numberFormatException.getMessage(), periodArray[1], numberFormatException);
|
||||
throw numberFormatException;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that sets the events information for the retention schedule action definition type.
|
||||
* @param dispositionActionDefinition
|
||||
* @param retentionScheduleActionDefinition
|
||||
*/
|
||||
private void mapEventsProperties(DispositionActionDefinition dispositionActionDefinition, RetentionScheduleActionDefinition retentionScheduleActionDefinition)
|
||||
{
|
||||
List<RecordsManagementEvent> events = dispositionActionDefinition.getEvents();
|
||||
if (events != null && !events.isEmpty())
|
||||
{
|
||||
List<String> eventNames = events.stream()
|
||||
.map(RecordsManagementEvent::getName)
|
||||
.collect(Collectors.toList());
|
||||
retentionScheduleActionDefinition.setEvents(eventNames);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that sets the optional information for the retention schedule type.
|
||||
* @param retentionSchedule
|
||||
* @param schedule
|
||||
* @param includeParam
|
||||
*/
|
||||
public void mapRetentionScheduleOptionalInfo(RetentionSchedule retentionSchedule, DispositionSchedule schedule, List<String> includeParam)
|
||||
{
|
||||
if (includeParam != null && !includeParam.isEmpty() && includeParam.contains("actions"))
|
||||
{
|
||||
List<RetentionScheduleActionDefinition> actions = schedule.getDispositionActionDefinitions().stream()
|
||||
.map(this::mapRetentionScheduleActionDefData)
|
||||
.collect(Collectors.toList());
|
||||
retentionSchedule.setActions(actions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this method is used for creation of retention schedule action definition params
|
||||
* @param nodeInfo retention schedule action definition
|
||||
* @return Map<QName, Serializable>
|
||||
*/
|
||||
public Map<QName, Serializable> createRetentionActionDefinitionParams(RetentionScheduleActionDefinition nodeInfo)
|
||||
{
|
||||
Map<QName, Serializable> actionDefinitionParams= new HashMap<>();
|
||||
|
||||
String retentionActionName = nodeInfo.getName();
|
||||
|
||||
if (nodeInfo.getName().equals(RetentionSteps.DESTROY_NODE.stepName) ||
|
||||
nodeInfo.getName().equals(RetentionSteps.DESTROY_CONTENT.stepName))
|
||||
{
|
||||
retentionActionName = "destroy";
|
||||
}
|
||||
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_NAME, retentionActionName);
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_DESCRIPTION, nodeInfo.getDescription());
|
||||
StringBuilder retentionPeriod = new StringBuilder(nodeInfo.getPeriod()).append("|");
|
||||
|
||||
if (isPeriodAmountApplicable(nodeInfo.getPeriod()))
|
||||
{
|
||||
retentionPeriod.append(nodeInfo.getPeriodAmount());
|
||||
}
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD, retentionPeriod.toString());
|
||||
QName periodProperty = QName.createQName(nodeInfo.getPeriodProperty(), namespaceService);
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_PERIOD_PROPERTY, periodProperty);
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_EVENT_COMBINATION,
|
||||
nodeInfo.isEligibleOnFirstCompleteEvent());
|
||||
boolean combineConditions = nodeInfo.getName().equals(RetentionSteps.ACCESSION.stepName) && nodeInfo.isCombineRetentionStepConditions();
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_COMBINE_DISPOSITION_STEP_CONDITIONS, combineConditions);
|
||||
|
||||
if(nodeInfo.getLocation() != null && nodeInfo.getName().equals(RetentionSteps.TRANSFER.stepName))
|
||||
{
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_LOCATION,
|
||||
nodeInfo.getLocation());
|
||||
}
|
||||
List<String> inputEvents = nodeInfo.getEvents();
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_EVENT, (Serializable) inputEvents);
|
||||
|
||||
if (RetentionSteps.DESTROY_CONTENT.stepName.equals(nodeInfo.getName()))
|
||||
{
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY, "ghost");
|
||||
}
|
||||
else if (RetentionSteps.DESTROY_NODE.stepName.equals(nodeInfo.getName()))
|
||||
{
|
||||
actionDefinitionParams.put(RecordsManagementModel.PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY, "delete");
|
||||
}
|
||||
return actionDefinitionParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method is used retrieve retention schedule action details
|
||||
* @param retentionScheduleNodeRef nodeRef
|
||||
* @return List<DispositionActionDefinition>
|
||||
*/
|
||||
public List<DispositionActionDefinition> getRetentionActions(NodeRef retentionScheduleNodeRef)
|
||||
{
|
||||
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(
|
||||
retentionScheduleNodeRef,
|
||||
RecordsManagementModel.ASSOC_DISPOSITION_ACTION_DEFINITIONS,
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
// we are getting disposition action definitions based on retention schedule child association.
|
||||
// setting the index value for each action.
|
||||
List<DispositionActionDefinition> actions;
|
||||
actions = IntStream.range(0, assocs.size())
|
||||
.mapToObj(index ->
|
||||
{
|
||||
ChildAssociationRef assoc = assocs.get(index);
|
||||
return new DispositionActionDefinitionImpl(
|
||||
services.getRecordsManagementEventService(),
|
||||
services.getRecordsManagementActionService(),
|
||||
nodeService,
|
||||
assoc.getChildRef(),
|
||||
index);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method is used to check period amount applicable or not for particular period
|
||||
* @param period period
|
||||
* @return boolean
|
||||
*/
|
||||
private boolean isPeriodAmountApplicable(String period)
|
||||
{
|
||||
// periodAmount property only applicable for following periods
|
||||
// day, week, month, quarter, year and duration
|
||||
return period.equals(RetentionPeriod.DAY.periodName) || period.equals(RetentionPeriod.MONTH.periodName) || period.equals(RetentionPeriod.QUARTER.periodName)
|
||||
|| period.equals(RetentionPeriod.WEEK.periodName) || period.equals(RetentionPeriod.XML_DURATION.periodName) || period.equals(RetentionPeriod.YEAR.periodName);
|
||||
}
|
||||
}
|
@@ -92,7 +92,7 @@ public class SearchTypesFactory
|
||||
boolean includeRecords = false;
|
||||
boolean includeSubTypes = false;
|
||||
|
||||
if (q != null)
|
||||
if (q != null && q.getTree() != null)
|
||||
{
|
||||
// filtering via "where" clause
|
||||
MapBasedQueryWalker propertyWalker = new MapBasedQueryWalker(listFolderChildrenEqualsQueryProperties, null);
|
||||
@@ -101,11 +101,11 @@ public class SearchTypesFactory
|
||||
Boolean isUnfiledRecordFolder = propertyWalker.getProperty(UnfiledChild.PARAM_IS_UNFILED_RECORD_FOLDER,
|
||||
WhereClauseParser.EQUALS, Boolean.class);
|
||||
Boolean isRecord = propertyWalker.getProperty(UnfiledChild.PARAM_IS_RECORD, WhereClauseParser.EQUALS, Boolean.class);
|
||||
if ((isUnfiledRecordFolder != null && isUnfiledRecordFolder.booleanValue()) || (isRecord != null && !isRecord.booleanValue()))
|
||||
if (checkIncludeUnfiledRecordFolders(isUnfiledRecordFolder, isRecord))
|
||||
{
|
||||
includeUnfiledRecordFolders = true;
|
||||
}
|
||||
else if ((isUnfiledRecordFolder != null && !isUnfiledRecordFolder.booleanValue()) || (isRecord != null && isRecord.booleanValue()))
|
||||
else if (checkIncludeRecords(isUnfiledRecordFolder, isRecord))
|
||||
{
|
||||
includeRecords = true;
|
||||
}
|
||||
@@ -199,11 +199,11 @@ public class SearchTypesFactory
|
||||
WhereClauseParser.EQUALS, Boolean.class);
|
||||
Boolean isRecordCategory = propertyWalker.getProperty(RecordCategoryChild.PARAM_IS_RECORD_CATEGORY, WhereClauseParser.EQUALS, Boolean.class);
|
||||
|
||||
if ((isRecordFolder != null && isRecordFolder.booleanValue()) || (isRecordCategory != null && !isRecordCategory.booleanValue()))
|
||||
if (checkIncludeUnfiledRecordFolders(isRecordFolder, isRecordCategory))
|
||||
{
|
||||
includeRecordFolders = true;
|
||||
}
|
||||
else if ((isRecordFolder != null && !isRecordFolder.booleanValue()) || (isRecordCategory != null && isRecordCategory.booleanValue()))
|
||||
else if (checkIncludeRecords(isRecordFolder, isRecordCategory))
|
||||
{
|
||||
includeRecordCategories = true;
|
||||
}
|
||||
@@ -291,4 +291,16 @@ public class SearchTypesFactory
|
||||
|
||||
return new Pair<>(filterNodeTypeQName, filterIncludeSubTypes);
|
||||
}
|
||||
|
||||
private static boolean checkIncludeRecords(Boolean isUnfiledRecordFolder, Boolean isRecord)
|
||||
{
|
||||
return (isUnfiledRecordFolder != null && !isUnfiledRecordFolder.booleanValue()) || (isRecord != null
|
||||
&& isRecord.booleanValue());
|
||||
}
|
||||
|
||||
private static boolean checkIncludeUnfiledRecordFolders(Boolean isUnfiledRecordFolder, Boolean isRecord)
|
||||
{
|
||||
return (isUnfiledRecordFolder != null && isUnfiledRecordFolder.booleanValue()) || (isRecord != null
|
||||
&& !isRecord.booleanValue());
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
public record BulkCancellationEntry(String reason) {}
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.alfresco.rest.api.search.model.Query;
|
||||
|
||||
public record HoldBulkOperation(@JsonProperty(required = true) Query query, @JsonProperty(required = true) HoldBulkOperationType op) {}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
public record HoldBulkOperationEntry(String bulkStatusId, long totalItems){}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
/**
|
||||
* This enum represents the types of bulk operations that can be performed on holds
|
||||
*/
|
||||
public enum HoldBulkOperationType
|
||||
{
|
||||
/**
|
||||
* The ADD operation represents adding items to a hold in bulk.
|
||||
*/
|
||||
ADD
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public record HoldBulkStatusEntry(String bulkStatusId, Date startTime, Date endTime, long processedItems, long errorsCount,
|
||||
long totalItems, String lastError, String status, String cancellationReason, HoldBulkOperation holdBulkOperation) {
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
/**
|
||||
* Retention event values
|
||||
*/
|
||||
public enum RetentionEvents
|
||||
{
|
||||
CASE_CLOSED("case_closed"),
|
||||
ABOLISHED("abolished"),
|
||||
RE_DESIGNATED("re_designated"),
|
||||
NO_LONGER_NEEDED("no_longer_needed"),
|
||||
SUPERSEDED("superseded"),
|
||||
VERSIONED("versioned"),
|
||||
STUDY_COMPLETE("study_complete"),
|
||||
TRAINING_COMPLETE("training_complete"),
|
||||
TRANSFERRED_INACTIVE_STORAGE("related_record_trasfered_inactive_storage"),
|
||||
OBSOLETE("obsolete"),
|
||||
ALLOWANCES_GRANTED_TERMINATED("all_allowances_granted_are_terminated"),
|
||||
WGI_ACTION_COMPLETE("WGI_action_complete"),
|
||||
SEPARATION("separation"),
|
||||
CASE_COMPLETE("case_complete"),
|
||||
DECLASSIFICATION_REVIEW("declassification_review");
|
||||
|
||||
public final String eventName;
|
||||
|
||||
RetentionEvents(String eventName)
|
||||
{
|
||||
this.eventName = eventName;
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
/**
|
||||
* Retention period values
|
||||
*/
|
||||
public enum RetentionPeriod
|
||||
{
|
||||
DAY("day"),
|
||||
END_OF_FINANCIAL_MONTH("fmend"),
|
||||
END_OF_FINANCIAL_QUARTER("fqend"),
|
||||
END_OF_FINANCIAL_YEAR("fyend"),
|
||||
IMMEDIATELY("immediately"),
|
||||
END_OF_MONTH("monthend"),
|
||||
END_OF_QUARTER("quarterend"),
|
||||
END_OF_YEAR("yearend"),
|
||||
MONTH("month"),
|
||||
NONE("none"),
|
||||
QUARTER("quarter"),
|
||||
WEEK("week"),
|
||||
XML_DURATION("duration"),
|
||||
YEAR("year");
|
||||
|
||||
public final String periodName;
|
||||
|
||||
RetentionPeriod(String periodName)
|
||||
{
|
||||
this.periodName = periodName;
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* retention schedule
|
||||
*/
|
||||
@Data
|
||||
public class RetentionSchedule
|
||||
{
|
||||
private String id ;
|
||||
private String parentId;
|
||||
private String authority;
|
||||
private String instructions;
|
||||
private boolean isRecordLevel;
|
||||
private boolean isUnpublishedUpdates;
|
||||
private List<RetentionScheduleActionDefinition> actions;
|
||||
|
||||
public boolean getIsRecordLevel()
|
||||
{
|
||||
return isRecordLevel;
|
||||
}
|
||||
|
||||
public void setIsRecordLevel(boolean recordLevel)
|
||||
{
|
||||
isRecordLevel = recordLevel;
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* retention schedule action definition
|
||||
*/
|
||||
@Data
|
||||
public class RetentionScheduleActionDefinition
|
||||
{
|
||||
private String id;
|
||||
private String name;
|
||||
private String description;
|
||||
private int periodAmount;
|
||||
private String period;
|
||||
private String periodProperty;
|
||||
private boolean combineRetentionStepConditions;
|
||||
private List<String> events;
|
||||
private boolean eligibleOnFirstCompleteEvent;
|
||||
private boolean retainRecordMetadataAfterDestruction;
|
||||
private String location;
|
||||
private int index;
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.model;
|
||||
|
||||
/**
|
||||
* Retention steps values
|
||||
*/
|
||||
public enum RetentionSteps
|
||||
{
|
||||
RETAIN("retain"),
|
||||
CUTOFF("cutoff"),
|
||||
TRANSFER("transfer"),
|
||||
ACCESSION("accession"),
|
||||
DESTROY_CONTENT("destroyContent"),
|
||||
DESTROY_NODE("destroyNode");
|
||||
|
||||
public final String stepName;
|
||||
|
||||
RetentionSteps(String stepName)
|
||||
{
|
||||
this.stepName = stepName;
|
||||
}
|
||||
}
|
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.retentionschedule;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionScheduleImpl;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnprocessableContentException;
|
||||
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.Parameters;
|
||||
import org.alfresco.rm.rest.api.impl.ApiNodesModelFactory;
|
||||
import org.alfresco.rm.rest.api.impl.FilePlanComponentsApiUtils;
|
||||
import org.alfresco.rm.rest.api.model.RetentionEvents;
|
||||
import org.alfresco.rm.rest.api.model.RetentionPeriod;
|
||||
import org.alfresco.rm.rest.api.model.RetentionScheduleActionDefinition;
|
||||
import org.alfresco.rm.rest.api.model.RetentionSteps;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.alfresco.module.org_alfresco_module_rm.util.RMParameterCheck.checkNotBlank;
|
||||
import static org.alfresco.util.ParameterCheck.mandatory;
|
||||
|
||||
/**
|
||||
* Retention schedule action relation is used to perform the retention schedule step operations.
|
||||
*/
|
||||
@RelationshipResource(name = "retention-steps", entityResource = RetentionScheduleEntityResource.class, title = "Retention Schedule Action")
|
||||
public class RetentionScheduleActionRelation implements RelationshipResourceAction.Read<RetentionScheduleActionDefinition>,
|
||||
RelationshipResourceAction.Create<RetentionScheduleActionDefinition>
|
||||
{
|
||||
private FilePlanComponentsApiUtils apiUtils;
|
||||
protected NodeService nodeService;
|
||||
private RecordsManagementServiceRegistry service;
|
||||
private ApiNodesModelFactory nodesModelFactory;
|
||||
|
||||
public void setApiUtils(FilePlanComponentsApiUtils apiUtils)
|
||||
{
|
||||
this.apiUtils = apiUtils;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setNodesModelFactory(ApiNodesModelFactory nodesModelFactory)
|
||||
{
|
||||
this.nodesModelFactory = nodesModelFactory;
|
||||
}
|
||||
|
||||
public void setRecordsManagementServiceRegistry(RecordsManagementServiceRegistry service)
|
||||
{
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title="Create a retention schedule step for the particular retention schedule using the 'retentionScheduleId'")
|
||||
public List<RetentionScheduleActionDefinition> create(String retentionScheduleId, List<RetentionScheduleActionDefinition> nodeInfos, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("retentionScheduleId", retentionScheduleId);
|
||||
mandatory("entity", nodeInfos);
|
||||
mandatory("parameters", parameters);
|
||||
NodeRef retentionScheduleNodeRef = apiUtils.lookupAndValidateNodeType(retentionScheduleId, RecordsManagementModel.TYPE_DISPOSITION_SCHEDULE);
|
||||
// validation for the order of the step
|
||||
retentionScheduleStepValidation(retentionScheduleNodeRef, nodeInfos.get(0));
|
||||
// request property validation
|
||||
retentionScheduleRequestValidation(nodeInfos.get(0));
|
||||
// create the parameters for the action definition
|
||||
Map<QName, Serializable> actionDefinitionParams = nodesModelFactory.createRetentionActionDefinitionParams(nodeInfos.get(0));
|
||||
// create the child association from the schedule to the action definition
|
||||
NodeRef actionNodeRef = this.nodeService.createNode(retentionScheduleNodeRef,
|
||||
RecordsManagementModel.ASSOC_DISPOSITION_ACTION_DEFINITIONS,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
|
||||
QName.createValidLocalName(nodeInfos.get(0).getName())),
|
||||
RecordsManagementModel.TYPE_DISPOSITION_ACTION_DEFINITION, actionDefinitionParams).getChildRef();
|
||||
DispositionSchedule dispositionSchedule = new DispositionScheduleImpl(service, nodeService, retentionScheduleNodeRef);
|
||||
DispositionActionDefinition dispositionActionDefinition = dispositionSchedule.getDispositionActionDefinition(actionNodeRef.getId());
|
||||
List<RetentionScheduleActionDefinition> responseActions = new ArrayList<>();
|
||||
if (dispositionActionDefinition != null)
|
||||
{
|
||||
responseActions.add(nodesModelFactory.mapRetentionScheduleActionDefData(dispositionActionDefinition));
|
||||
}
|
||||
return responseActions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Return a paged list of retention schedule action definition based on the 'retentionScheduleId'")
|
||||
public CollectionWithPagingInfo<RetentionScheduleActionDefinition> readAll(String retentionScheduleId, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("retentionScheduleId", retentionScheduleId);
|
||||
mandatory("parameters", parameters);
|
||||
NodeRef retentionScheduleNodeRef = apiUtils.lookupAndValidateNodeType(retentionScheduleId, RecordsManagementModel.TYPE_DISPOSITION_SCHEDULE);
|
||||
List<DispositionActionDefinition> actions = nodesModelFactory.getRetentionActions(retentionScheduleNodeRef);
|
||||
List<RetentionScheduleActionDefinition> actionDefinitionList = actions.stream()
|
||||
.map(nodesModelFactory::mapRetentionScheduleActionDefData)
|
||||
.collect(Collectors.toList());
|
||||
return CollectionWithPagingInfo.asPaged(parameters.getPaging(), actionDefinitionList, false,
|
||||
actionDefinitionList.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* this method is used to validate the order of the retention schedule step
|
||||
* @param retentionScheduleNodeRef nodeRef
|
||||
* @param retentionScheduleActionDefinition retention schedule action definition
|
||||
*/
|
||||
private void retentionScheduleStepValidation(NodeRef retentionScheduleNodeRef, RetentionScheduleActionDefinition retentionScheduleActionDefinition)
|
||||
{
|
||||
if (checkStepNameIsEmpty(retentionScheduleActionDefinition.getName()))
|
||||
{
|
||||
throw new IllegalArgumentException("'name' parameter is mandatory when creating a disposition action definition");
|
||||
}
|
||||
|
||||
List<DispositionActionDefinition> actions = nodesModelFactory.getRetentionActions(retentionScheduleNodeRef);
|
||||
Set<String> completedActions = new HashSet<>();
|
||||
if (!actions.isEmpty())
|
||||
{
|
||||
completedActions = actions.stream()
|
||||
.map(DispositionActionDefinition::getName)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
if (completedActions.contains("destroy"))
|
||||
{
|
||||
throw new ConstraintViolatedException("Invalid Step - destroy action is already added. No other action is allowed after Destroy.");
|
||||
}
|
||||
|
||||
if (checkStepAlreadyExists(completedActions, retentionScheduleActionDefinition.getName()))
|
||||
{
|
||||
throw new ConstraintViolatedException("Invalid Step - This step already exists. You can’t create it again. Only transfer action is allowed multiple times.");
|
||||
}
|
||||
|
||||
if (firstStepValidation(actions, retentionScheduleActionDefinition.getName()))
|
||||
{
|
||||
throw new UnprocessableContentException("Invalid Step - cutoff or retain should be the first step");
|
||||
}
|
||||
|
||||
if (isCutOffStepAllowed(completedActions, retentionScheduleActionDefinition.getName()))
|
||||
{
|
||||
throw new ConstraintViolatedException("Invalid Step - Can't use cutoff after transfer or accession");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkStepNameIsEmpty(String name)
|
||||
{
|
||||
return name == null || name.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* this method is used to validate the request of the retention schedule
|
||||
* @param retentionScheduleActionDefinition retention schedule action definition
|
||||
*/
|
||||
private void retentionScheduleRequestValidation(RetentionScheduleActionDefinition retentionScheduleActionDefinition)
|
||||
{
|
||||
// step name validation
|
||||
if (invalidStepNameCheck(retentionScheduleActionDefinition.getName()))
|
||||
{
|
||||
throw new InvalidArgumentException("name value is invalid : " +retentionScheduleActionDefinition.getName());
|
||||
}
|
||||
|
||||
validatePeriodAndPeriodProperty(retentionScheduleActionDefinition);
|
||||
|
||||
// event name validation
|
||||
if (invalidEventNameCheck(retentionScheduleActionDefinition.getEvents()))
|
||||
{
|
||||
throw new InvalidArgumentException("event value is invalid: " + retentionScheduleActionDefinition.getEvents());
|
||||
}
|
||||
|
||||
if (validateCombineRetentionStepConditionsForNonAccessionStep(retentionScheduleActionDefinition))
|
||||
{
|
||||
throw new IllegalArgumentException("combineRetentionStepConditions property is only valid for accession step. Not valid for :" + retentionScheduleActionDefinition.getName());
|
||||
}
|
||||
|
||||
if (validateLocationForNonTransferStep(retentionScheduleActionDefinition))
|
||||
{
|
||||
throw new IllegalArgumentException("location property is only valid for transfer step. Not valid for :" + retentionScheduleActionDefinition.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePeriodAndPeriodProperty(RetentionScheduleActionDefinition retentionScheduleActionDefinition)
|
||||
{
|
||||
// period value validation
|
||||
if (invalidPeriodCheck(retentionScheduleActionDefinition.getPeriod()))
|
||||
{
|
||||
throw new InvalidArgumentException("period value is invalid : " +retentionScheduleActionDefinition.getPeriod());
|
||||
}
|
||||
|
||||
// periodProperty validation
|
||||
List<String> validPeriodProperties = Arrays.asList("cm:created", "rma:cutOffDate", "rma:dispositionAsOf");
|
||||
if (validPeriodProperties.stream().noneMatch(retentionScheduleActionDefinition.getPeriodProperty()::equals))
|
||||
{
|
||||
throw new InvalidArgumentException("periodProperty value is invalid: " + retentionScheduleActionDefinition.getPeriodProperty());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validateCombineRetentionStepConditionsForNonAccessionStep(RetentionScheduleActionDefinition retentionScheduleActionDefinition)
|
||||
{
|
||||
return !retentionScheduleActionDefinition.getName().equals(RetentionSteps.ACCESSION.stepName)
|
||||
&& retentionScheduleActionDefinition.isCombineRetentionStepConditions();
|
||||
}
|
||||
|
||||
private boolean validateLocationForNonTransferStep(RetentionScheduleActionDefinition retentionScheduleActionDefinition)
|
||||
{
|
||||
return retentionScheduleActionDefinition.getLocation() != null
|
||||
&& !retentionScheduleActionDefinition.getName().equals(RetentionSteps.TRANSFER.stepName)
|
||||
&& !retentionScheduleActionDefinition.getLocation().isEmpty();
|
||||
}
|
||||
|
||||
private boolean checkStepAlreadyExists(Set<String> completedActions, String stepName)
|
||||
{
|
||||
return completedActions.contains(stepName) && !stepName.equals(RetentionSteps.TRANSFER.stepName);
|
||||
}
|
||||
|
||||
private boolean firstStepValidation(List<DispositionActionDefinition> actions, String stepName)
|
||||
{
|
||||
return actions.isEmpty()
|
||||
&& !stepName.equals(RetentionSteps.CUTOFF.stepName) && (!stepName.equals(RetentionSteps.RETAIN.stepName));
|
||||
}
|
||||
|
||||
private boolean isCutOffStepAllowed(Set<String> completedActions, String stepName)
|
||||
{
|
||||
return (completedActions.contains(RetentionSteps.TRANSFER.stepName) || completedActions.contains(RetentionSteps.ACCESSION.stepName))
|
||||
&& stepName.equals(RetentionSteps.CUTOFF.stepName);
|
||||
}
|
||||
|
||||
private boolean invalidStepNameCheck(String stepName)
|
||||
{
|
||||
return stepName != null && Arrays.stream(RetentionSteps.values())
|
||||
.noneMatch(retentionStep -> retentionStep.stepName.equals(stepName));
|
||||
}
|
||||
|
||||
private boolean invalidPeriodCheck(String period)
|
||||
{
|
||||
return period != null && Arrays.stream(RetentionPeriod.values())
|
||||
.noneMatch(retentionPeriod -> retentionPeriod.periodName.equals(period));
|
||||
}
|
||||
|
||||
private boolean invalidEventNameCheck(List<String> events)
|
||||
{
|
||||
return !events.isEmpty() && events.stream()
|
||||
.anyMatch(event -> Arrays.stream(RetentionEvents.values())
|
||||
.noneMatch(retentionEvent -> retentionEvent.eventName.equals(event)));
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.retentionschedule;
|
||||
|
||||
import org.alfresco.rest.framework.resource.EntityResource;
|
||||
|
||||
/**
|
||||
* Retention schedule entity resource
|
||||
*/
|
||||
@EntityResource(name="retention-schedules", title = "Retention Schedule")
|
||||
public class RetentionScheduleEntityResource
|
||||
{
|
||||
|
||||
}
|
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.rm.rest.api.retentionschedule;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
|
||||
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.core.exceptions.UnprocessableContentException;
|
||||
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.Parameters;
|
||||
import org.alfresco.rm.rest.api.impl.ApiNodesModelFactory;
|
||||
import org.alfresco.rm.rest.api.impl.FilePlanComponentsApiUtils;
|
||||
import org.alfresco.rm.rest.api.model.RetentionSchedule;
|
||||
import org.alfresco.rm.rest.api.recordcategories.RecordCategoriesEntityResource;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_DISPOSITION_AUTHORITY;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_DISPOSITION_INSTRUCTIONS;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_RECORD_LEVEL_DISPOSITION;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.TYPE_RECORD_CATEGORY;
|
||||
import static org.alfresco.module.org_alfresco_module_rm.util.RMParameterCheck.checkNotBlank;
|
||||
import static org.alfresco.util.ParameterCheck.mandatory;
|
||||
|
||||
/**
|
||||
* Retention schedule relation is used perform retention schedule operation for a record category.
|
||||
*/
|
||||
@RelationshipResource(name = "retention-schedules", entityResource = RecordCategoriesEntityResource.class, title = "Retention Schedule")
|
||||
public class RetentionScheduleRelation implements RelationshipResourceAction.Read<RetentionSchedule>,
|
||||
RelationshipResourceAction.Create<RetentionSchedule>
|
||||
{
|
||||
|
||||
private FilePlanComponentsApiUtils apiUtils;
|
||||
private ApiNodesModelFactory nodesModelFactory;
|
||||
private DispositionService dispositionService;
|
||||
protected NodeService nodeService;
|
||||
|
||||
public void setApiUtils(FilePlanComponentsApiUtils apiUtils)
|
||||
{
|
||||
this.apiUtils = apiUtils;
|
||||
}
|
||||
|
||||
public void setNodesModelFactory(ApiNodesModelFactory nodesModelFactory)
|
||||
{
|
||||
this.nodesModelFactory = nodesModelFactory;
|
||||
}
|
||||
|
||||
public void setDispositionService(DispositionService dispositionService)
|
||||
{
|
||||
this.dispositionService = dispositionService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title="Create a retention schedule for the particular record category using the 'recordCategoryId'")
|
||||
public List<RetentionSchedule> create(String recordCategoryId, List<RetentionSchedule> nodeInfos, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("recordCategoryId", recordCategoryId);
|
||||
mandatory("entity", nodeInfos);
|
||||
mandatory("parameters", parameters);
|
||||
NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, recordCategoryId);
|
||||
|
||||
if (checkCategoryHasAssocFolder(parentNodeRef) && nodeInfos.get(0).getIsRecordLevel())
|
||||
{
|
||||
throw new UnprocessableContentException("Record level retention schedule cannot be created for a record category having folder associated.");
|
||||
}
|
||||
List<RetentionSchedule> result = new ArrayList<>();
|
||||
// Create the disposition schedule
|
||||
Map<QName, Serializable> dsProps = new HashMap<>();
|
||||
dsProps.put(PROP_DISPOSITION_AUTHORITY, nodeInfos.get(0).getAuthority());
|
||||
dsProps.put(PROP_DISPOSITION_INSTRUCTIONS, nodeInfos.get(0).getInstructions());
|
||||
dsProps.put(PROP_RECORD_LEVEL_DISPOSITION, nodeInfos.get(0).getIsRecordLevel());
|
||||
DispositionSchedule dispositionSchedule = dispositionService.createDispositionSchedule(parentNodeRef, dsProps);
|
||||
RetentionSchedule retentionSchedule = nodesModelFactory.mapRetentionScheduleData(dispositionSchedule);
|
||||
result.add(retentionSchedule);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean checkCategoryHasAssocFolder(NodeRef nodeRef)
|
||||
{
|
||||
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
|
||||
return assocs.stream()
|
||||
.map(assoc -> nodeService.getType(assoc.getChildRef()))
|
||||
.anyMatch(nodeType -> nodeType.equals(RecordsManagementModel.TYPE_RECORD_FOLDER));
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Return a paged list of retention schedule based on the 'recordCategoryId'")
|
||||
public CollectionWithPagingInfo<RetentionSchedule> readAll(String recordCategoryId, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("recordCategoryId", recordCategoryId);
|
||||
mandatory("parameters", parameters);
|
||||
NodeRef parentNodeRef = apiUtils.lookupAndValidateNodeType(recordCategoryId, TYPE_RECORD_CATEGORY);
|
||||
DispositionSchedule schedule = dispositionService.getDispositionSchedule(parentNodeRef);
|
||||
RetentionSchedule retentionSchedule = nodesModelFactory.mapRetentionScheduleData(schedule);
|
||||
List<RetentionSchedule> retentionScheduleList = new ArrayList<>();
|
||||
nodesModelFactory.mapRetentionScheduleOptionalInfo(retentionSchedule, schedule, parameters.getInclude());
|
||||
retentionScheduleList.add(retentionSchedule);
|
||||
return CollectionWithPagingInfo.asPaged(parameters.getPaging(), retentionScheduleList, false,
|
||||
retentionScheduleList.size());
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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 info that defines the Information Governance Retention Schedule REST API
|
||||
*/
|
||||
@WebApi(name="gs", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
package org.alfresco.rm.rest.api.retentionschedule;
|
||||
import org.alfresco.rest.framework.Api;
|
||||
import org.alfresco.rest.framework.WebApi;
|
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.test.integration.bulk.hold;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkCancellationRequest;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.BulkOperation;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkMonitor;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkServiceImpl;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkStatus;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkStatus.Status;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||
import org.alfresco.rest.api.search.model.Query;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.extensions.webscripts.GUID;
|
||||
|
||||
/**
|
||||
* Hold bulk service integration test.
|
||||
*/
|
||||
@SuppressWarnings({ "PMD.TestClassWithoutTestCases", "PMD.JUnit4TestShouldUseTestAnnotation" })
|
||||
public class HoldBulkServiceTest extends BaseRMTestCase
|
||||
{
|
||||
private static final int RECORD_COUNT = 10;
|
||||
private final SearchService searchServiceMock = mock(SearchService.class);
|
||||
private final ResultSet resultSet = mock(ResultSet.class);
|
||||
private HoldBulkServiceImpl holdBulkService;
|
||||
private HoldBulkMonitor holdBulkMonitor;
|
||||
|
||||
@Override
|
||||
protected void initServices()
|
||||
{
|
||||
super.initServices();
|
||||
holdBulkMonitor = (HoldBulkMonitor) applicationContext.getBean("holdBulkMonitor");
|
||||
holdBulkService = (HoldBulkServiceImpl) applicationContext.getBean("holdBulkService");
|
||||
holdBulkService.setSearchService(searchServiceMock);
|
||||
Mockito.when(searchServiceMock.query(any(SearchParameters.class))).thenReturn(resultSet);
|
||||
}
|
||||
|
||||
public void testCancelBulkOperation()
|
||||
{
|
||||
doBehaviourDrivenTest(new BehaviourDrivenTest()
|
||||
{
|
||||
private NodeRef hold;
|
||||
private HoldBulkStatus holdBulkStatus;
|
||||
private final ResultSet resultSet = mock(ResultSet.class);
|
||||
|
||||
public void given()
|
||||
{
|
||||
Mockito.when(resultSet.getNumberFound()).thenReturn(4L);
|
||||
Mockito.when(resultSet.hasMore()).thenReturn(false).thenReturn(true).thenReturn(false);
|
||||
Mockito.when(resultSet.getNodeRefs())
|
||||
.thenAnswer((Answer<List<NodeRef>>) invocationOnMock -> {
|
||||
await().pollDelay(1, SECONDS).until(() -> true);
|
||||
return List.of(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate()),
|
||||
new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate()));
|
||||
});
|
||||
// create a hold
|
||||
hold = holdService.createHold(filePlan, GUID.generate(), GUID.generate(), GUID.generate());
|
||||
}
|
||||
|
||||
public void when()
|
||||
{
|
||||
BulkOperation bulkOperation = new BulkOperation(new Query("afts", "*", ""), "ADD");
|
||||
// execute the bulk operation
|
||||
holdBulkStatus = holdBulkService.execute(hold, bulkOperation);
|
||||
// cancel the bulk operation
|
||||
holdBulkMonitor.cancelBulkOperation(holdBulkStatus.bulkStatusId(),
|
||||
new BulkCancellationRequest("No reason"));
|
||||
await().atMost(10, SECONDS)
|
||||
.until(() -> Objects.equals(
|
||||
holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId()).getStatus(),
|
||||
Status.CANCELLED.getValue()));
|
||||
}
|
||||
|
||||
public void then()
|
||||
{
|
||||
holdBulkStatus = holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId());
|
||||
assertNotNull(holdBulkStatus.startTime());
|
||||
assertNotNull(holdBulkStatus.endTime());
|
||||
assertEquals(holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId()).getStatus(),
|
||||
HoldBulkStatus.Status.CANCELLED.getValue());
|
||||
assertEquals(holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId()).cancellationReason(),
|
||||
"No reason");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testAddRecordsToHoldViaBulk()
|
||||
{
|
||||
doBehaviourDrivenTest(new BehaviourDrivenTest()
|
||||
{
|
||||
private NodeRef hold;
|
||||
private NodeRef recordFolder;
|
||||
private HoldBulkStatus holdBulkStatus;
|
||||
private final List<NodeRef> records = new ArrayList<>(RECORD_COUNT);
|
||||
|
||||
public void given()
|
||||
{
|
||||
Mockito.when(resultSet.getNumberFound()).thenReturn(Long.valueOf(RECORD_COUNT));
|
||||
Mockito.when(resultSet.hasMore()).thenReturn(false).thenReturn(false);
|
||||
// create a hold
|
||||
hold = holdService.createHold(filePlan, GUID.generate(), GUID.generate(), GUID.generate());
|
||||
|
||||
// create a record folder that contains records
|
||||
NodeRef recordCategory = filePlanService.createRecordCategory(filePlan, GUID.generate());
|
||||
recordFolder = recordFolderService.createRecordFolder(recordCategory, GUID.generate());
|
||||
for (int i = 0; i < RECORD_COUNT; i++)
|
||||
{
|
||||
records.add(
|
||||
recordService.createRecordFromContent(recordFolder, GUID.generate(), ContentModel.TYPE_CONTENT,
|
||||
null, null));
|
||||
}
|
||||
Mockito.when(resultSet.getNodeRefs()).thenReturn(records).thenReturn(records)
|
||||
.thenReturn(Collections.emptyList());
|
||||
|
||||
// assert current states
|
||||
assertFalse(freezeService.isFrozen(recordFolder));
|
||||
assertFalse(freezeService.hasFrozenChildren(recordFolder));
|
||||
for (NodeRef record : records)
|
||||
{
|
||||
assertFalse(freezeService.isFrozen(record));
|
||||
}
|
||||
|
||||
// additional check for child held caching
|
||||
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_HELD_CHILDREN));
|
||||
assertEquals(0, nodeService.getProperty(recordFolder, PROP_HELD_CHILDREN_COUNT));
|
||||
}
|
||||
|
||||
public void when()
|
||||
{
|
||||
BulkOperation bulkOperation = new BulkOperation(new Query("afts", "*", ""), "ADD");
|
||||
// execute the bulk operation
|
||||
holdBulkStatus = holdBulkService.execute(hold, bulkOperation);
|
||||
await().atMost(10, SECONDS)
|
||||
.until(() -> Objects.equals(
|
||||
holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId()).getStatus(),
|
||||
Status.DONE.getValue()));
|
||||
}
|
||||
|
||||
public void then()
|
||||
{
|
||||
holdBulkStatus = holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId());
|
||||
assertNotNull(holdBulkStatus.startTime());
|
||||
assertNotNull(holdBulkStatus.endTime());
|
||||
assertEquals(RECORD_COUNT, holdBulkStatus.totalItems());
|
||||
assertEquals(RECORD_COUNT, holdBulkStatus.processedItems());
|
||||
assertEquals(0, holdBulkStatus.errorsCount());
|
||||
assertEquals(holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId()).getStatus(),
|
||||
HoldBulkStatus.Status.DONE.getValue());
|
||||
|
||||
// record is held
|
||||
for (NodeRef record : records)
|
||||
{
|
||||
assertTrue(freezeService.isFrozen(record));
|
||||
}
|
||||
|
||||
// record folder has frozen children
|
||||
assertFalse(freezeService.isFrozen(recordFolder));
|
||||
assertTrue(freezeService.hasFrozenChildren(recordFolder));
|
||||
|
||||
// record folder is not held
|
||||
assertFalse(holdService.getHeld(hold).contains(recordFolder));
|
||||
assertFalse(holdService.heldBy(recordFolder, true).contains(hold));
|
||||
|
||||
for (NodeRef record : records)
|
||||
{
|
||||
// hold contains record
|
||||
assertTrue(holdService.getHeld(hold).contains(record));
|
||||
assertTrue(holdService.heldBy(record, true).contains(hold));
|
||||
}
|
||||
|
||||
// additional check for child held caching
|
||||
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_HELD_CHILDREN));
|
||||
assertEquals(RECORD_COUNT, nodeService.getProperty(recordFolder, PROP_HELD_CHILDREN_COUNT));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testAddRecordFolderToHoldViaBulk()
|
||||
{
|
||||
doBehaviourDrivenTest(new BehaviourDrivenTest()
|
||||
{
|
||||
private NodeRef hold;
|
||||
private NodeRef recordFolder;
|
||||
private final List<NodeRef> records = new ArrayList<>(RECORD_COUNT);
|
||||
private HoldBulkStatus holdBulkStatus;
|
||||
|
||||
public void given()
|
||||
{
|
||||
Mockito.when(resultSet.getNumberFound()).thenReturn(1L);
|
||||
Mockito.when(resultSet.hasMore()).thenReturn(false).thenReturn(false);
|
||||
// create a hold
|
||||
hold = holdService.createHold(filePlan, GUID.generate(), GUID.generate(), GUID.generate());
|
||||
|
||||
// create a record folder that contains records
|
||||
NodeRef recordCategory = filePlanService.createRecordCategory(filePlan, GUID.generate());
|
||||
recordFolder = recordFolderService.createRecordFolder(recordCategory, GUID.generate());
|
||||
for (int i = 0; i < RECORD_COUNT; i++)
|
||||
{
|
||||
records.add(
|
||||
recordService.createRecordFromContent(recordFolder, GUID.generate(), ContentModel.TYPE_CONTENT,
|
||||
null, null));
|
||||
}
|
||||
Mockito.when(resultSet.getNodeRefs()).thenReturn(Collections.singletonList(recordFolder))
|
||||
.thenReturn(Collections.singletonList(recordFolder)).thenReturn(Collections.emptyList());
|
||||
|
||||
// assert current states
|
||||
assertFalse(freezeService.isFrozen(recordFolder));
|
||||
assertFalse(freezeService.hasFrozenChildren(recordFolder));
|
||||
for (NodeRef record : records)
|
||||
{
|
||||
assertFalse(freezeService.isFrozen(record));
|
||||
}
|
||||
|
||||
// additional check for child held caching
|
||||
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_HELD_CHILDREN));
|
||||
assertEquals(0, nodeService.getProperty(recordFolder, PROP_HELD_CHILDREN_COUNT));
|
||||
}
|
||||
|
||||
public void when()
|
||||
{
|
||||
BulkOperation bulkOperation = new BulkOperation(new Query("afts", "*", ""), "ADD");
|
||||
// execute the bulk operation
|
||||
holdBulkStatus = holdBulkService.execute(hold, bulkOperation);
|
||||
await().atMost(10, SECONDS)
|
||||
.until(() -> Objects.equals(
|
||||
holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId()).getStatus(),
|
||||
Status.DONE.getValue()));
|
||||
}
|
||||
|
||||
public void then()
|
||||
{
|
||||
holdBulkStatus = holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId());
|
||||
assertNotNull(holdBulkStatus.startTime());
|
||||
assertNotNull(holdBulkStatus.endTime());
|
||||
assertEquals(1, holdBulkStatus.totalItems());
|
||||
assertEquals(1, holdBulkStatus.processedItems());
|
||||
assertEquals(0, holdBulkStatus.errorsCount());
|
||||
assertEquals(holdBulkMonitor.getBulkStatus(holdBulkStatus.bulkStatusId()).getStatus(),
|
||||
HoldBulkStatus.Status.DONE.getValue());
|
||||
|
||||
for (NodeRef record : records)
|
||||
{
|
||||
// record is held
|
||||
assertTrue(freezeService.isFrozen(record));
|
||||
assertFalse(holdService.getHeld(hold).contains(record));
|
||||
assertTrue(holdService.heldBy(record, true).contains(hold));
|
||||
}
|
||||
|
||||
// record folder has frozen children
|
||||
assertTrue(freezeService.isFrozen(recordFolder));
|
||||
assertTrue(freezeService.hasFrozenChildren(recordFolder));
|
||||
|
||||
// hold contains record folder
|
||||
assertTrue(holdService.getHeld(hold).contains(recordFolder));
|
||||
assertTrue(holdService.heldBy(recordFolder, true).contains(hold));
|
||||
|
||||
// additional check for child held caching
|
||||
assertTrue(nodeService.hasAspect(recordFolder, ASPECT_HELD_CHILDREN));
|
||||
assertEquals(RECORD_COUNT, nodeService.getProperty(recordFolder, PROP_HELD_CHILDREN_COUNT));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
@@ -51,6 +51,8 @@ import org.alfresco.module.org_alfresco_module_rm.job.publish.PublishExecutorReg
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils;
|
||||
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
|
||||
import org.junit.Assert;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
@@ -437,19 +439,12 @@ public class DispositionServiceImplTest extends BaseRMTestCase
|
||||
|
||||
// Check the disposition schedule
|
||||
checkDispositionSchedule(ds, "testCreateDispositionSchedule", "testCreateDispositionSchedule", false);
|
||||
}
|
||||
});
|
||||
|
||||
// Failure: create disposition schedule on container with existing disposition schedule
|
||||
doTestInTransaction(new FailureTest
|
||||
(
|
||||
"Can not create a disposition schedule on a container with an existing disposition schedule"
|
||||
)
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
utils.createBasicDispositionSchedule(rmContainer);
|
||||
// Failure: create disposition schedule on container with existing disposition schedule
|
||||
Assert.assertThrows(ConstraintViolatedException.class,
|
||||
() -> {
|
||||
utils.createBasicDispositionSchedule(rmContainer);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -492,19 +487,12 @@ public class DispositionServiceImplTest extends BaseRMTestCase
|
||||
// Check the disposition schedule
|
||||
checkDispositionSchedule(testA, "testA", "testA", false);
|
||||
checkDispositionSchedule(testB, "testB", "testB", false);
|
||||
}
|
||||
});
|
||||
|
||||
// Failure: create disposition schedule on container with existing disposition schedule
|
||||
doTestInTransaction(new FailureTest
|
||||
(
|
||||
"Can not create a disposition schedule on container with an existing disposition schedule"
|
||||
)
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
utils.createBasicDispositionSchedule(mhContainer11);
|
||||
// Failure: create disposition schedule on container with existing disposition schedule
|
||||
Assert.assertThrows(ConstraintViolatedException.class,
|
||||
() -> {
|
||||
utils.createBasicDispositionSchedule(rmContainer);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
# Version label
|
||||
version.major=23
|
||||
version.minor=3
|
||||
version.minor=4
|
||||
version.revision=0
|
||||
version.label=
|
||||
|
||||
|
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.bulk;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.DefaultHoldBulkMonitor;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkProcessDetails;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkStatus;
|
||||
import org.alfresco.module.org_alfresco_module_rm.bulk.hold.HoldBulkStatusAndProcessDetails;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
public class DefaultHoldBulkMonitorUnitTest
|
||||
{
|
||||
|
||||
@Mock
|
||||
private SimpleCache<String, HoldBulkStatus> holdProgressCache;
|
||||
|
||||
@Mock
|
||||
private SimpleCache<Pair<String, String>, HoldBulkProcessDetails> holdProcessRegistry;
|
||||
|
||||
private DefaultHoldBulkMonitor holdBulkMonitor;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
MockitoAnnotations.openMocks(this);
|
||||
holdBulkMonitor = new DefaultHoldBulkMonitor();
|
||||
holdBulkMonitor.setHoldProgressCache(holdProgressCache);
|
||||
holdBulkMonitor.setHoldProcessRegistry(holdProcessRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateBulkStatus()
|
||||
{
|
||||
HoldBulkStatus status = new HoldBulkStatus("bulkStatusId", null, null, 0L, 0L, 0L, null, false, null);
|
||||
|
||||
holdBulkMonitor.updateBulkStatus(status);
|
||||
|
||||
Mockito.verify(holdProgressCache).put("bulkStatusId", status);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterProcess()
|
||||
{
|
||||
NodeRef holdRef = new NodeRef("workspace://SpacesStore/holdId");
|
||||
String processId = "processId";
|
||||
when(holdProcessRegistry.get(new Pair<>(holdRef.getId(), processId))).thenReturn(null);
|
||||
|
||||
holdBulkMonitor.registerProcess(holdRef, processId, null);
|
||||
|
||||
Mockito.verify(holdProcessRegistry)
|
||||
.put(new Pair<>(holdRef.getId(), processId), new HoldBulkProcessDetails(processId, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBulkStatusesWithProcessDetailsReturnsEmptyListWhenNoProcessesWithProcessDetails()
|
||||
{
|
||||
when(holdProcessRegistry.getKeys()).thenReturn(Collections.emptyList());
|
||||
assertEquals(Collections.emptyList(), holdBulkMonitor.getBulkStatusesWithProcessDetails("holdId"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBulkStatus()
|
||||
{
|
||||
BulkOperation bulkOperation = mock(BulkOperation.class);
|
||||
HoldBulkStatus status1 = new HoldBulkStatus("process1", new Date(1000), new Date(2000), 0L, 0L, 0L, null, false,
|
||||
null);
|
||||
when(holdProcessRegistry.get(new Pair<>("holdId", "process1"))).thenReturn(
|
||||
new HoldBulkProcessDetails("process1", null, bulkOperation));
|
||||
when(holdProgressCache.get("process1")).thenReturn(status1);
|
||||
|
||||
assertEquals(new HoldBulkStatusAndProcessDetails(status1,
|
||||
new HoldBulkProcessDetails(status1.bulkStatusId(), null, bulkOperation)),
|
||||
holdBulkMonitor.getBulkStatusWithProcessDetails("holdId", "process1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNonExistingBulkStatus()
|
||||
{
|
||||
BulkOperation bulkOperation = mock(BulkOperation.class);
|
||||
when(holdProcessRegistry.get(new Pair<>("holdId", "process1"))).thenReturn(
|
||||
new HoldBulkProcessDetails("process1", null, bulkOperation));
|
||||
when(holdProgressCache.get("process1")).thenReturn(null);
|
||||
|
||||
assertNull(holdBulkMonitor.getBulkStatusWithProcessDetails("holdId", "process1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBulkStatusesForHoldReturnsSortedStatusesWithProcessDetails()
|
||||
{
|
||||
BulkOperation bulkOperation = mock(BulkOperation.class);
|
||||
HoldBulkStatus status1 = new HoldBulkStatus("process1", new Date(1000), new Date(2000), 0L, 0L, 0L, null, false,
|
||||
null);
|
||||
HoldBulkStatus status2 = new HoldBulkStatus("process2", new Date(3000), null, 0L, 0L, 0L, null, false, null);
|
||||
HoldBulkStatus status3 = new HoldBulkStatus("process3", new Date(4000), null, 0L, 0L, 0L, null, false, null);
|
||||
HoldBulkStatus status4 = new HoldBulkStatus("process4", new Date(500), new Date(800), 0L, 0L, 0L, null, false,
|
||||
null);
|
||||
HoldBulkStatus status5 = new HoldBulkStatus("process5", null, null, 0L, 0L, 0L, null, false, null);
|
||||
|
||||
when(holdProcessRegistry.getKeys()).thenReturn(
|
||||
Arrays.asList(new Pair<>("holdId", "process1"), new Pair<>("holdId", "process2"),
|
||||
new Pair<>("holdId", "process3"), new Pair<>("holdId", "process4"), new Pair<>("holdId", "process5"))
|
||||
);
|
||||
when(holdProcessRegistry.get(new Pair<>("holdId", "process1"))).thenReturn(
|
||||
new HoldBulkProcessDetails("process1", null, bulkOperation));
|
||||
when(holdProcessRegistry.get(new Pair<>("holdId", "process2"))).thenReturn(
|
||||
new HoldBulkProcessDetails("process2", null, bulkOperation));
|
||||
when(holdProcessRegistry.get(new Pair<>("holdId", "process3"))).thenReturn(
|
||||
new HoldBulkProcessDetails("process3", null, bulkOperation));
|
||||
when(holdProcessRegistry.get(new Pair<>("holdId", "process4"))).thenReturn(
|
||||
new HoldBulkProcessDetails("process4", null, bulkOperation));
|
||||
when(holdProcessRegistry.get(new Pair<>("holdId", "process5"))).thenReturn(
|
||||
new HoldBulkProcessDetails("process5", null, bulkOperation));
|
||||
when(holdProgressCache.get("process1")).thenReturn(status1);
|
||||
when(holdProgressCache.get("process2")).thenReturn(status2);
|
||||
when(holdProgressCache.get("process3")).thenReturn(status3);
|
||||
when(holdProgressCache.get("process4")).thenReturn(status4);
|
||||
when(holdProgressCache.get("process5")).thenReturn(status5);
|
||||
|
||||
assertEquals(Arrays.asList(status5, status3, status2, status1, status4).stream().map(
|
||||
status -> new HoldBulkStatusAndProcessDetails(status,
|
||||
new HoldBulkProcessDetails(status.bulkStatusId(), null, bulkOperation))).toList(),
|
||||
holdBulkMonitor.getBulkStatusesWithProcessDetails("holdId"));
|
||||
}
|
||||
}
|
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2024 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.module.org_alfresco_module_rm.disposition;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
|
||||
import org.alfresco.rm.rest.api.impl.ApiNodesModelFactory;
|
||||
import org.alfresco.rm.rest.api.model.RetentionSchedule;
|
||||
import org.alfresco.rm.rest.api.model.RetentionScheduleActionDefinition;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.Period;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Retention schedule model unit test
|
||||
*/
|
||||
public class RetentionScheduleModelUnitTest extends BaseUnitTest
|
||||
{
|
||||
private static final String AUTHORITY = "authority";
|
||||
private static final String INSTRUCTIONS = "instructions";
|
||||
private static final String RETAIN_STEP = "retain";
|
||||
|
||||
@InjectMocks
|
||||
private ApiNodesModelFactory apiNodesModelFactory;
|
||||
|
||||
@Mock
|
||||
DispositionSchedule dispositionSchedule;
|
||||
|
||||
@Mock
|
||||
DispositionActionDefinition dispositionActionDefinition;
|
||||
|
||||
@Test
|
||||
public void mapRetentionScheduleDataTest()
|
||||
{
|
||||
// Mock data
|
||||
NodeRef nodeRef = generateNodeRef(RecordsManagementModel.TYPE_DISPOSITION_SCHEDULE, true);
|
||||
ChildAssociationRef childAssociationRef = generateChildAssociationRef(filePlan, record);
|
||||
when(dispositionSchedule.getDispositionAuthority()).thenReturn(AUTHORITY);
|
||||
when(dispositionSchedule.getDispositionInstructions()).thenReturn(INSTRUCTIONS);
|
||||
when(dispositionSchedule.getNodeRef()).thenReturn(nodeRef);
|
||||
when(dispositionSchedule.isRecordLevelDisposition()).thenReturn(false);
|
||||
when(mockedNodeService.getPrimaryParent(nodeRef)).thenReturn(childAssociationRef);
|
||||
// Call the method
|
||||
RetentionSchedule actualResult = apiNodesModelFactory.mapRetentionScheduleData(dispositionSchedule);
|
||||
|
||||
//Expected Result
|
||||
RetentionSchedule expectedResult = new RetentionSchedule();
|
||||
expectedResult.setId(nodeRef.getId());
|
||||
expectedResult.setParentId(filePlan.getId());
|
||||
expectedResult.setAuthority(AUTHORITY);
|
||||
expectedResult.setInstructions(INSTRUCTIONS);
|
||||
|
||||
// Assertions
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapRetentionScheduleActionDefDataTest()
|
||||
{
|
||||
// Mock data
|
||||
NodeRef nodeRef = generateNodeRef(RecordsManagementModel.TYPE_DISPOSITION_SCHEDULE, true);
|
||||
String period = "month|10";
|
||||
ChildAssociationRef childAssociationRef = generateChildAssociationRef(filePlan, record);
|
||||
when(dispositionActionDefinition.getNodeRef()).thenReturn(nodeRef);
|
||||
when(dispositionActionDefinition.getName()).thenReturn(RETAIN_STEP);
|
||||
when(dispositionActionDefinition.getDescription()).thenReturn("Description");
|
||||
when(dispositionActionDefinition.getIndex()).thenReturn(1);
|
||||
when(dispositionActionDefinition.getGhostOnDestroy()).thenReturn("ghost");
|
||||
when(dispositionActionDefinition.getPeriod()).thenReturn(new Period(period));
|
||||
when(dispositionActionDefinition.getLocation()).thenReturn("location");
|
||||
when(dispositionActionDefinition.getId()).thenReturn(nodeRef.getId());
|
||||
when(mockedNodeService.getPrimaryParent(nodeRef)).thenReturn(childAssociationRef);
|
||||
// Call the method
|
||||
RetentionScheduleActionDefinition actualResult = apiNodesModelFactory.mapRetentionScheduleActionDefData(dispositionActionDefinition);
|
||||
|
||||
//Expected Result
|
||||
RetentionScheduleActionDefinition expectedResult = getRetentionScheduleActionDefinition(nodeRef);
|
||||
|
||||
// Assertion
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
|
||||
private static RetentionScheduleActionDefinition getRetentionScheduleActionDefinition(NodeRef nodeRef)
|
||||
{
|
||||
RetentionScheduleActionDefinition expectedResult = new RetentionScheduleActionDefinition();
|
||||
expectedResult.setId(nodeRef.getId());
|
||||
expectedResult.setName(RETAIN_STEP);
|
||||
expectedResult.setDescription("Description");
|
||||
expectedResult.setIndex(1);
|
||||
expectedResult.setLocation("location");
|
||||
expectedResult.setPeriod("month");
|
||||
expectedResult.setPeriodAmount(10);
|
||||
expectedResult.setRetainRecordMetadataAfterDestruction(true);
|
||||
return expectedResult;
|
||||
}
|
||||
}
|
@@ -93,15 +93,15 @@ public class RMv33HoldAuditEntryValuesPatchUnitTest
|
||||
verify(mockedRecordsManagementQueryDAO, times(1)).updatePropertyStringValueEntity(deleteHoldPropertyStringValueEntity);
|
||||
|
||||
assertEquals("Add To Hold", addToHoldPropertyStringValueEntity.getStringValue());
|
||||
assertEquals("add to hold", addToHoldPropertyStringValueEntity.getStringEndLower());
|
||||
assertEquals("add to hold", addToHoldPropertyStringValueEntity.getStringLower());
|
||||
assertEquals(Long.valueOf(770_786_109L), addToHoldPropertyStringValueEntity.getStringCrc());
|
||||
|
||||
assertEquals("Remove From Hold", removeFromHoldPropertyStringValueEntity.getStringValue());
|
||||
assertEquals("remove from hold", removeFromHoldPropertyStringValueEntity.getStringEndLower());
|
||||
assertEquals("remove from hold", removeFromHoldPropertyStringValueEntity.getStringLower());
|
||||
assertEquals(Long.valueOf(2_967_613_012L), removeFromHoldPropertyStringValueEntity.getStringCrc());
|
||||
|
||||
assertEquals("Delete Hold", deleteHoldPropertyStringValueEntity.getStringValue());
|
||||
assertEquals("delete hold", deleteHoldPropertyStringValueEntity.getStringEndLower());
|
||||
assertEquals("delete hold", deleteHoldPropertyStringValueEntity.getStringLower());
|
||||
assertEquals(Long.valueOf(132_640_810L), deleteHoldPropertyStringValueEntity.getStringCrc());
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -40,6 +40,8 @@ tags:
|
||||
description: Retrieve and manage unfiled record folders
|
||||
- name: holds
|
||||
description: Retrieve and manage holds
|
||||
- name: retention-schedules
|
||||
description: Perform retention schedule specific operations
|
||||
|
||||
paths:
|
||||
## GS sites
|
||||
@@ -2314,6 +2316,145 @@ paths:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
'/holds/{holdId}/bulk-statuses':
|
||||
get:
|
||||
tags:
|
||||
- holds
|
||||
operationId: listBulkStatuses
|
||||
summary: Get bulk statuses
|
||||
description: |
|
||||
Gets bulk statuses for hold with id **holdId**.
|
||||
parameters:
|
||||
- $ref: '#/parameters/holdIdParam'
|
||||
- $ref: '#/parameters/skipCountParam'
|
||||
- $ref: '#/parameters/maxItemsParam'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/HoldBulkStatusPaging'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: **holdId** is not a valid format
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to read **holdId**
|
||||
'404':
|
||||
description: "**holdId** does not exist"
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
'/holds/{holdId}/bulk-statuses/{bulkStatusId}':
|
||||
get:
|
||||
tags:
|
||||
- holds
|
||||
operationId: getBulkStatus
|
||||
summary: Get a bulk status
|
||||
description: |
|
||||
Gets a bulk status specified by **bulkStatusId** for **holdId**.
|
||||
parameters:
|
||||
- $ref: '#/parameters/holdIdParam'
|
||||
- $ref: '#/parameters/bulkStatusId'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/HoldBulkStatus'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: **holdId** or **bulkStatusId** is not a valid format
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to read **holdId**
|
||||
'404':
|
||||
description: "**holdId** or **bulkStatusId** does not exist"
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
'/holds/{holdId}/bulk-statuses/{bulkStatusId}/cancel':
|
||||
post:
|
||||
tags:
|
||||
- holds
|
||||
operationId: cancelBulkStatus
|
||||
summary: Cancel the bulk operation
|
||||
description: |
|
||||
Cancels the bulk operation specified by **bulkStatusId** for **holdId**.
|
||||
parameters:
|
||||
- $ref: '#/parameters/holdIdParam'
|
||||
- $ref: '#/parameters/bulkStatusId'
|
||||
- in: body
|
||||
name: cancelReason
|
||||
description: Cancel reason.
|
||||
required: false
|
||||
schema:
|
||||
$ref: '#/definitions/BulkBodyCancel'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: **holdId** or **bulkStatusId** is not a valid format
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to cancel the bulk process for **holdId** and **bulkStatusId**
|
||||
'404':
|
||||
description: "**holdId** or **bulkStatusId** does not exist"
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
'/holds/{holdId}/bulk':
|
||||
post:
|
||||
tags:
|
||||
- holds
|
||||
operationId: startHoldBulkProcess
|
||||
summary: Start the hold bulk process
|
||||
description: |
|
||||
Start the asynchronous bulk process for a hold with id **holdId** based on search query results.
|
||||
|
||||
```JSON
|
||||
For example, the following JSON body starts the bulk process to add search query results
|
||||
as children of a hold.
|
||||
|
||||
{
|
||||
"query": {
|
||||
"query": "SITE:swsdp and TYPE:content",
|
||||
"language": "afts"
|
||||
},
|
||||
"op": "ADD"
|
||||
}
|
||||
```
|
||||
parameters:
|
||||
- $ref: '#/parameters/holdIdParam'
|
||||
- in: body
|
||||
name: holdBulkOperation
|
||||
description: Bulk operation.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/HoldBulkOperation'
|
||||
responses:
|
||||
'202':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/HoldBulkOperationEntry'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: **holdId** is not a valid format or **HoldBulkOperation** is not valid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to start the bulk process for **holdId**
|
||||
'404':
|
||||
description: "**holdId** does not exist"
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
'/holds/{holdId}/delete':
|
||||
post:
|
||||
tags:
|
||||
@@ -2495,7 +2636,196 @@ paths:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
##retention-schedule
|
||||
'/record-categories/{recordCategoryId}/retention-schedules':
|
||||
post:
|
||||
tags:
|
||||
- retention-schedules
|
||||
summary: Create a retention schedule
|
||||
description: |
|
||||
Create a retention schedule.
|
||||
|
||||
For example, using the following JSON body will create a retention schedule:
|
||||
```JSON
|
||||
{
|
||||
"authority": "Retention Authority",
|
||||
"instructions": "Retention Instructions",
|
||||
"isRecordLevel": false
|
||||
}
|
||||
```
|
||||
|
||||
operationId: createRetentionSchedule
|
||||
parameters:
|
||||
- $ref: '#/parameters/recordCategoryIdParam'
|
||||
- in: body
|
||||
name: retentionNodeBodyCreate
|
||||
description: |
|
||||
The retention schedule information to create.
|
||||
schema:
|
||||
$ref: '#/definitions/RetentionNodeBodyCreate'
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
'201':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/RetentionScheduleResponse'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: value of recordCategoryId is invalid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to create retention schedule
|
||||
'404':
|
||||
description: recordCategoryId does not exist
|
||||
'409':
|
||||
description: Retention schedule already exist for the given recordCategoryId
|
||||
'422':
|
||||
description: Record level retention schedule cannot be created for a record category having folder associated
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
get:
|
||||
tags:
|
||||
- retention-schedules
|
||||
summary: Get the retention schedule for a record category
|
||||
description: |
|
||||
Get the retention schedule for a record category.
|
||||
|
||||
You can use the **include** parameter (include=actions) to return additional information.
|
||||
|
||||
operationId: getRetentionScheduleList
|
||||
parameters:
|
||||
- $ref: '#/parameters/recordCategoryIdParam'
|
||||
- $ref: '#/parameters/retentionScheduleIncludeParam'
|
||||
- $ref: '#/parameters/skipCountParam'
|
||||
- $ref: '#/parameters/maxItemsParam'
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/RetentionScheduleResponseList'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: value of recordCategoryId is invalid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to get retention schedule
|
||||
'404':
|
||||
description: recordCategoryId does not exist
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
'/retention-schedules/{retentionScheduleId}/retention-steps':
|
||||
post:
|
||||
tags:
|
||||
- retention-schedules
|
||||
summary: Create a step in the retention schedule
|
||||
description: |
|
||||
Create a step in the retention schedule.
|
||||
|
||||
Order of steps:
|
||||
* "**retain**" or "**cutoff**" should be first
|
||||
* can't use "**cutoff**" after "**transfer**" or "**accession**"
|
||||
* only the "**transfer**" action is allowed multiple times
|
||||
* no steps are allowed after "**destroy**"
|
||||
|
||||
For example, the following JSON body will create a step in the retention schedule:
|
||||
```JSON
|
||||
{
|
||||
"name":"accession",
|
||||
"description":"Step Description",
|
||||
"periodAmount": 2,
|
||||
"period":"month",
|
||||
"periodProperty":"cm:created",
|
||||
"combineRetentionStepConditions": false,
|
||||
"events":["versioned"],
|
||||
"eligibleOnFirstCompleteEvent": true
|
||||
}
|
||||
```
|
||||
operationId: createRetentionScheduleAction
|
||||
parameters:
|
||||
- $ref: '#/parameters/retentionScheduleIdParam'
|
||||
- in: body
|
||||
name: nodeBodyCreate
|
||||
description: |
|
||||
The retention schedule steps information to create.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RetentionStepNodeBodyCreate'
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
'201':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/RetentionStepNodeBodyResponse'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: value of retentionScheduleId is invalid
|
||||
Invalid parameter (e.g. event, period, periodProperty)
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to create retention schedule step
|
||||
'404':
|
||||
description: retentionScheduleId does not exist
|
||||
'409':
|
||||
description: |
|
||||
* Invalid Step - Can't use Cut Off after Transfer or Accession
|
||||
* Invalid Step - Destroy action already completed. Can't do any other Action
|
||||
* Invalid Step - This step already exists. You can’t create this step [Transfer action is allowed many times]
|
||||
'422':
|
||||
description: Cut Off or Retain should be the first step
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
get:
|
||||
tags:
|
||||
- retention-schedules
|
||||
summary: Get the list of steps in the retention schedule
|
||||
description: |
|
||||
Get the list of steps in the retention schedule.
|
||||
operationId: getRetentionScheduleActionList
|
||||
parameters:
|
||||
- $ref: '#/parameters/retentionScheduleIdParam'
|
||||
- $ref: '#/parameters/skipCountParam'
|
||||
- $ref: '#/parameters/maxItemsParam'
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/RetentionStepsNodeBodyResponse'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: value of retentionScheduleId is invalid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to get retention schedule steps
|
||||
'404':
|
||||
description: retentionScheduleId does not exist
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
parameters:
|
||||
## File plans
|
||||
filePlanEntryIncludeParam:
|
||||
@@ -2862,6 +3192,12 @@ parameters:
|
||||
description: The identifier of a child of a hold.
|
||||
required: true
|
||||
type: string
|
||||
bulkStatusId:
|
||||
name: bulkStatusId
|
||||
in: path
|
||||
description: The identifier of a bulk process.
|
||||
required: true
|
||||
type: string
|
||||
## Record
|
||||
recordIdParam:
|
||||
name: recordId
|
||||
@@ -2955,6 +3291,22 @@ parameters:
|
||||
If true, then a name clash will cause an attempt to auto rename by finding a unique name using an integer suffix.
|
||||
required: false
|
||||
type: boolean
|
||||
## RetentionSchedule
|
||||
retentionScheduleIdParam:
|
||||
name: retentionScheduleId
|
||||
in: path
|
||||
description:
|
||||
The identifier of a retention schedule.
|
||||
required: true
|
||||
type: string
|
||||
retentionScheduleIncludeParam:
|
||||
name: include
|
||||
in: query
|
||||
description: |
|
||||
Returns additional information about the retention schedule actions. Any optional field from the response model can be requested. For example:
|
||||
* actions
|
||||
required: false
|
||||
type: string
|
||||
definitions:
|
||||
FilePlanComponentBodyUpdate:
|
||||
type: object
|
||||
@@ -4018,6 +4370,323 @@ definitions:
|
||||
properties:
|
||||
reason:
|
||||
type: string
|
||||
SearchRequestQuery:
|
||||
type: object
|
||||
required:
|
||||
- query
|
||||
properties:
|
||||
language:
|
||||
description: The query language in which the query is written.
|
||||
type: string
|
||||
default: afts
|
||||
enum:
|
||||
- afts
|
||||
- lucene
|
||||
- cmis
|
||||
userQuery:
|
||||
description: The search request typed in by the user
|
||||
type: string
|
||||
query:
|
||||
description: The query which may have been generated in some way from the userQuery
|
||||
type: string
|
||||
HoldBulkOperation:
|
||||
type: object
|
||||
properties:
|
||||
query:
|
||||
$ref: '#/definitions/SearchRequestQuery'
|
||||
op:
|
||||
description: The operation type.
|
||||
type: string
|
||||
default: ADD
|
||||
enum:
|
||||
- ADD
|
||||
HoldBulkOperationEntry:
|
||||
type: object
|
||||
properties:
|
||||
bulkStatusId:
|
||||
type: string
|
||||
totalItems:
|
||||
type: integer
|
||||
format: int64
|
||||
BulkBodyCancel:
|
||||
type: object
|
||||
properties:
|
||||
reason:
|
||||
type: string
|
||||
HoldBulkStatus:
|
||||
type: object
|
||||
properties:
|
||||
bulkStatusId:
|
||||
type: string
|
||||
startTime:
|
||||
type: string
|
||||
format: date-time
|
||||
endTime:
|
||||
type: string
|
||||
format: date-time
|
||||
processedItems:
|
||||
type: integer
|
||||
format: int64
|
||||
errorsCount:
|
||||
type: integer
|
||||
format: int64
|
||||
totalItems:
|
||||
type: integer
|
||||
format: int64
|
||||
lastError:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
enum:
|
||||
- PENDING
|
||||
- IN PROGRESS
|
||||
- DONE
|
||||
- CANCELLED
|
||||
cancellationReason:
|
||||
type: string
|
||||
holdBulkOperation:
|
||||
$ref: '#/definitions/HoldBulkOperation'
|
||||
HoldBulkStatusEntry:
|
||||
type: object
|
||||
required:
|
||||
- entry
|
||||
properties:
|
||||
entry:
|
||||
$ref: '#/definitions/HoldBulkStatus'
|
||||
HoldBulkStatusPaging:
|
||||
type: object
|
||||
properties:
|
||||
list:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
$ref: '#/definitions/Pagination'
|
||||
entries:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/HoldBulkStatusEntry'
|
||||
RetentionNodeBodyCreate:
|
||||
type: object
|
||||
properties:
|
||||
authority:
|
||||
type: string
|
||||
description: |
|
||||
Authority name for the retention schedule.
|
||||
instructions:
|
||||
type: string
|
||||
description: |
|
||||
Required instructions for the retention schedule.
|
||||
isRecordLevel:
|
||||
type: boolean
|
||||
default: false
|
||||
description: |
|
||||
This field is used to specify whether the retention schedule needs to be applied in the folder level or record level.
|
||||
True will cause the the retention schedule to apply to records and false will cause the retention schedule to apply to record folders.
|
||||
This cannot be changed once items start being managed by the retention schedule.
|
||||
RetentionScheduleResponse:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
parentId:
|
||||
type: string
|
||||
authority:
|
||||
type: string
|
||||
instructions:
|
||||
type: string
|
||||
isRecordLevel:
|
||||
type: boolean
|
||||
unpublishedUpdates:
|
||||
type: boolean
|
||||
RetentionScheduleResponseList:
|
||||
type: object
|
||||
properties:
|
||||
list:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
$ref: '#/definitions/Pagination'
|
||||
entries:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/FullRetentionScheduleResponse'
|
||||
FullRetentionScheduleResponse:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
parentId:
|
||||
type: string
|
||||
authority:
|
||||
type: string
|
||||
instructions:
|
||||
type: string
|
||||
isRecordLevel:
|
||||
type: boolean
|
||||
unpublishedUpdates:
|
||||
type: boolean
|
||||
actions:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Actions'
|
||||
Actions:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
periodAmount:
|
||||
type: integer
|
||||
period:
|
||||
type: string
|
||||
periodProperty:
|
||||
type: string
|
||||
combineRetentionStepConditions:
|
||||
type: boolean
|
||||
default: false
|
||||
eligibleOnFirstCompleteEvent:
|
||||
type: boolean
|
||||
default: true
|
||||
retainRecordMetadataAfterDestruction:
|
||||
type: boolean
|
||||
location:
|
||||
type: string
|
||||
events:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
index:
|
||||
type: integer
|
||||
RetentionStepNodeBodyCreate:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- description
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: |
|
||||
The valid names are:
|
||||
* retain
|
||||
* cutoff
|
||||
* accession
|
||||
* transfer
|
||||
* destroyContent
|
||||
* destroyNode
|
||||
|
||||
destroyNode step can be used to destroy content along with record metadata.
|
||||
In case, record metadata needs to be retained, then destroyContent step should be used.
|
||||
description:
|
||||
type: string
|
||||
description: |
|
||||
This property is used to provide the step description.
|
||||
periodAmount:
|
||||
type: integer
|
||||
description: |
|
||||
This property is only applicable for the following period values.
|
||||
* day
|
||||
* month
|
||||
* quarter
|
||||
* week
|
||||
* duration
|
||||
* year
|
||||
period:
|
||||
type: string
|
||||
description: |
|
||||
Valid values for the period.
|
||||
* day = Day
|
||||
* fmend = End Of Financial Month
|
||||
* fqend = End Of Financial Quarter
|
||||
* fyend = End Of Financial Year
|
||||
* immediately = Immediately
|
||||
* monthend = End Of Month
|
||||
* quarterend = End Of Quarter
|
||||
* yearend = End Of Year
|
||||
* month = Month
|
||||
* none = None
|
||||
* quarter = Quarter
|
||||
* week = Week
|
||||
* duration = XML Duration
|
||||
* year = Year
|
||||
|
||||
If you provide XML Duration for the period value, you need to specify a time interval using XML syntax.
|
||||
The syntax should take the form of:
|
||||
P = Period (required)
|
||||
nY = Number of years
|
||||
nM = Number of months
|
||||
nD = Number of days
|
||||
T = Start time of a time section (required if specifying hours, minutes, or seconds)
|
||||
nH = Number of hours
|
||||
nM = Number of minutes
|
||||
nS = Number of seconds
|
||||
For example, ‘P2M10D’ represents two months and ten days.
|
||||
periodProperty:
|
||||
type: string
|
||||
default: cm:created
|
||||
description: |
|
||||
Valid values for the periodProperty property
|
||||
* cm:created = Created Date (defult value)
|
||||
* rma:cutOffDate = Cut Off Date
|
||||
* rma:dispositionAsOf = Retention Action
|
||||
combineRetentionStepConditions:
|
||||
type: boolean
|
||||
description: |
|
||||
This property is only valid for **accession** step.
|
||||
This is used to specify whether to combine the period condition and events for the step execution or only consider one of them.
|
||||
For example:
|
||||
**periodCondition**: After a period of 2 months
|
||||
**eventsCondition**: Case Closed event
|
||||
This flag can be used to consider only (**periodCondition** or **eventsCondition**) or both of them at once.
|
||||
events:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: |
|
||||
Valid values for the events property
|
||||
* case_closed = Case Closed
|
||||
* abolished = Abolished
|
||||
* re_designated = Redesignated
|
||||
* no_longer_needed = No Longer Needed
|
||||
* superseded = Superseded
|
||||
* versioned = Versioned
|
||||
* study_complete = Study Complete
|
||||
* training_complete = Training Complete
|
||||
* related_record_trasfered_inactive_storage = Related Record Transferred to Inactive Storage
|
||||
* obsolete = Obsolete
|
||||
* all_allowances_granted_are_terminated = All Allowances Granted are Terminated
|
||||
* WGI_action_complete = WGI Action Complete
|
||||
* separation = Separation
|
||||
* case_complete = Case Complete
|
||||
* declassification_review = Declassification Review
|
||||
eligibleOnFirstCompleteEvent:
|
||||
type: boolean
|
||||
description: |
|
||||
* false = When all events have happened
|
||||
* true = Whichever event is earlier
|
||||
location:
|
||||
type: string
|
||||
description: |
|
||||
This property is only valid for transfer step
|
||||
RetentionStepNodeBodyResponse:
|
||||
type: object
|
||||
properties:
|
||||
actions:
|
||||
$ref: '#/definitions/Actions'
|
||||
RetentionStepsNodeBodyResponse:
|
||||
type: object
|
||||
properties:
|
||||
list:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
$ref: '#/definitions/Pagination'
|
||||
entries:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/RetentionStepNodeBodyResponse'
|
||||
##
|
||||
RequestBodyFile:
|
||||
type: object
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
10
core/pom.xml
10
core/pom.xml
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -47,11 +47,11 @@
|
||||
<artifactId>commons-math3</artifactId>
|
||||
<version>3.6.1</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.uuid/java-uuid-generator -->
|
||||
<dependency>
|
||||
<groupId>org.safehaus.jug</groupId>
|
||||
<artifactId>jug</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<classifier>asl</classifier>
|
||||
<groupId>com.fasterxml.uuid</groupId>
|
||||
<artifactId>java-uuid-generator</artifactId>
|
||||
<version>5.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
|
@@ -27,4 +27,9 @@ public class HttpClientException extends AlfrescoRuntimeException
|
||||
{
|
||||
super(msgId);
|
||||
}
|
||||
|
||||
public HttpClientException(String msgId, Throwable cause)
|
||||
{
|
||||
super(msgId, cause);
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ package org.alfresco.util;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
import org.safehaus.uuid.UUIDGenerator;
|
||||
import com.fasterxml.uuid.Generators;
|
||||
import org.alfresco.api.AlfrescoPublicApi;
|
||||
|
||||
/**
|
||||
@@ -69,7 +69,7 @@ public final class GUID
|
||||
public static String generate()
|
||||
{
|
||||
int randomInt = RANDOM.nextInt(SECURE_RANDOM_POOL_MAX_ITEMS);
|
||||
return UUIDGenerator.getInstance().generateRandomBasedUUID(SECURE_RANDOM_POOL[randomInt]).toString();
|
||||
return Generators.randomBasedGenerator(SECURE_RANDOM_POOL[randomInt]).generate().toString();
|
||||
}
|
||||
|
||||
// == Not sure if we need this functionality again (derekh) ==
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2023 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2024 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -67,4 +67,14 @@ public interface TransactionListener
|
||||
* be used only for cleaning up resources after a rollback has occurred.
|
||||
*/
|
||||
void afterRollback();
|
||||
|
||||
/**
|
||||
* Allows to provide a custom listener's order.
|
||||
* See {@link org.alfresco.repo.transaction.AlfrescoTransactionSupport#COMMIT_ORDER_NORMAL}
|
||||
* @return custom order or null for the default one
|
||||
*/
|
||||
default Integer getCustomOrder()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -132,7 +132,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.woodstox</groupId>
|
||||
<artifactId>woodstox-core</artifactId>
|
||||
<version>6.5.1</version>
|
||||
<version>7.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- the cxf libs were updated, see dependencyManagement section -->
|
||||
|
@@ -33,13 +33,13 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import com.fasterxml.uuid.Generators;
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.service.cmr.repository.datatype.Duration;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.safehaus.uuid.UUIDGenerator;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
|
||||
/**
|
||||
@@ -497,7 +497,7 @@ public class InMemoryTicketComponentImpl implements TicketComponent
|
||||
this.userName = userName;
|
||||
this.validDuration = validDuration;
|
||||
this.testDuration = validDuration.divide(2);
|
||||
final String guid = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
|
||||
final String guid = Generators.randomBasedGenerator().generate().toString();
|
||||
|
||||
this.ticketId = computeTicketId(expires, expiryDate, userName, guid);
|
||||
|
||||
|
@@ -238,6 +238,17 @@ public interface CustomModelService
|
||||
*/
|
||||
public NodeRef createDownloadNode(String modelName, boolean withAssociatedForm);
|
||||
|
||||
/**
|
||||
* Creates a downloadable archive file containing the custom model file and
|
||||
* if specified, its associated Share extension module file.
|
||||
*
|
||||
* @param modelName the model name to be exported
|
||||
* @param withAssociatedForm whether Share extension module file should be
|
||||
* included or not
|
||||
* @return reference to the node which will contain the archive file
|
||||
*/
|
||||
NodeRef createDownloadNode(String modelName, boolean withAssociatedForm, String downloadNodeName);
|
||||
|
||||
/**
|
||||
* Compiles the {@link M2Model}.
|
||||
*
|
||||
|
@@ -2,7 +2,7 @@
|
||||
* #%L
|
||||
* Alfresco Data model classes
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* Copyright (C) 2005 - 2024 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
@@ -78,6 +78,28 @@ public interface PermissionService
|
||||
*/
|
||||
public static final String GUEST_AUTHORITY = "ROLE_GUEST";
|
||||
|
||||
/**
|
||||
* The dynamic authority for the Admin service account.
|
||||
*/
|
||||
String ADMIN_SVC_AUTHORITY = "ROLE_ADMIN_SERVICE_ACCOUNT";
|
||||
|
||||
/**
|
||||
* The dynamic authority for the Collaborator service account.
|
||||
*/
|
||||
String COLLABORATOR_SVC_AUTHORITY = "ROLE_COLLABORATOR_SERVICE_ACCOUNT";
|
||||
|
||||
/**
|
||||
* The dynamic authority for the Editor service account.
|
||||
*/
|
||||
String EDITOR_SVC_AUTHORITY = "ROLE_EDITOR_SERVICE_ACCOUNT";
|
||||
|
||||
/**
|
||||
* A convenient set of service account authorities to simplify checks
|
||||
* for whether a given authority is a service account authority or not.
|
||||
*/
|
||||
Set<String> SVC_AUTHORITIES_SET = Set.of(ADMIN_SVC_AUTHORITY, COLLABORATOR_SVC_AUTHORITY,
|
||||
EDITOR_SVC_AUTHORITY);
|
||||
|
||||
/**
|
||||
* The permission for all - not defined in the model. Repsected in the code.
|
||||
*/
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@@ -84,7 +84,7 @@
|
||||
<include>org.alfresco:alfresco-core</include>
|
||||
<include>org.alfresco:alfresco-repository</include>
|
||||
<include>org.apache.commons:commons-compress</include>
|
||||
<include>org.safehaus.jug:jug</include>
|
||||
<include>com.fasterxml.uuid:java-uuid-generator</include>
|
||||
<include>org.alfresco.surf:spring-surf-core</include>
|
||||
<include>org.tukaani:xz</include>
|
||||
<include>org.apache.maven:maven-artifact</include>
|
||||
|
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
package org.alfresco.repo.module.tool;
|
||||
|
||||
import com.fasterxml.uuid.Generators;
|
||||
import de.schlichtherle.truezip.file.*;
|
||||
import de.schlichtherle.truezip.fs.FsSyncException;
|
||||
import de.schlichtherle.truezip.fs.archive.zip.JarDriver;
|
||||
@@ -34,7 +35,6 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.module.ModuleVersionNumber;
|
||||
import org.alfresco.service.cmr.module.ModuleDetails;
|
||||
import org.alfresco.service.cmr.module.ModuleInstallState;
|
||||
import org.safehaus.uuid.UUIDGenerator;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -916,7 +916,7 @@ public class ModuleManagementTool implements LogOutput
|
||||
*/
|
||||
private static String generateGuid()
|
||||
{
|
||||
return UUIDGenerator.getInstance().generateTimeBasedUUID().toString();
|
||||
return Generators.timeBasedGenerator().generate().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
@@ -1,6 +1,5 @@
|
||||
# Fetch image based on Tomcat 9.0, Java 17 and Rocky Linux 8
|
||||
# More infos about this image: https://github.com/Alfresco/alfresco-docker-base-tomcat
|
||||
FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux8-202306291245
|
||||
FROM alfresco/alfresco-base-tomcat:tomcat10-jre17-rockylinux9@sha256:395664f9d9be0c9f73d3b722a58fd559ee7231609b263dfe19502617652740e3
|
||||
|
||||
# Set default docker_context.
|
||||
ARG resource_path=target
|
||||
@@ -14,6 +13,9 @@ ARG USERID=33000
|
||||
# Set default environment args
|
||||
ARG TOMCAT_DIR=/usr/local/tomcat
|
||||
|
||||
# Needed for installation but make sure another USER directive is added after
|
||||
# this with a non-root user
|
||||
USER root
|
||||
|
||||
# Create prerequisite to store tools and properties
|
||||
RUN mkdir -p ${TOMCAT_DIR}/shared/classes/alfresco/extension/mimetypes && \
|
||||
@@ -61,13 +63,7 @@ RUN sed -i -e "s_appender.rolling.fileName\=alfresco.log_appender.rolling.fileNa
|
||||
sed -i -e "\$a\grant\ codeBase\ \"file:\$\{catalina.base\}\/webapps\/alfresco\/-\" \{\n\ permission\ java.security.AllPermission\;\n\};\ngrant\ codeBase\ \"file:\$\{catalina.base\}\/webapps\/_vti_bin\/-\" \{\n\ permission\ java.security.AllPermission\;\n\};\ngrant\ codeBase\ \"file:\$\{catalina.base\}\/webapps\/ROOT\/-\" \{\n\ permission org.apache.catalina.security.DeployXmlPermission \"ROOT\";\n\};" ${TOMCAT_DIR}/conf/catalina.policy
|
||||
|
||||
# fontconfig is required by Activiti worflow diagram generator
|
||||
# installing pinned dependencies as well
|
||||
RUN yum install -y fontconfig-2.13.1-4.el8 \
|
||||
dejavu-fonts-common-2.35-7.el8 \
|
||||
fontpackages-filesystem-1.44-22.el8 \
|
||||
freetype-2.9.1-9.el8 \
|
||||
libpng-1.6.34-5.el8 \
|
||||
dejavu-sans-fonts-2.35-7.el8 && \
|
||||
RUN yum install -y fontconfig-2.14.0-2.el9_1 && \
|
||||
yum clean all
|
||||
|
||||
# The standard configuration is to have all Tomcat files owned by root with group GROUPNAME and whilst owner has read/write privileges,
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>23.3.0.43</version>
|
||||
<version>23.4.0.55</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -1,3 +1,3 @@
|
||||
SOLR6_TAG=2.0.10
|
||||
SOLR6_TAG=2.0.12
|
||||
POSTGRES_TAG=15.4
|
||||
ACTIVEMQ_TAG=5.18.3-jre17-rockylinux8
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user