mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-10 14:11:58 +00:00
Compare commits
308 Commits
feature/Pr
...
23.3.0.80
Author | SHA1 | Date | |
---|---|---|---|
|
9cc93de7b2 | ||
|
55c9cf3407 | ||
|
120f45ba92 | ||
|
eacdbd3770 | ||
|
93d4701d80 | ||
|
64baf03818 | ||
|
e39606aec5 | ||
|
7581e07c3c | ||
|
a01d375e6f | ||
|
a98f44803a | ||
|
cabc38b386 | ||
|
9ed29967b7 | ||
|
b63a3eae9b | ||
|
1ce46c2039 | ||
|
278aa59302 | ||
|
51a51ecd6b | ||
|
10f4b10ae8 | ||
|
24575c436e | ||
|
25c4b677de | ||
|
6f13f36c5a | ||
|
db8b353fb1 | ||
|
2ccdee122a | ||
|
14c1b91a9b | ||
|
5b562edad1 | ||
|
19e577383a | ||
|
115997d367 | ||
|
de2effcefb | ||
|
79b78448e0 | ||
|
05c4f2282e | ||
|
228944c59c | ||
|
ec279bcd5d | ||
|
97770fd831 | ||
|
1a99c54074 | ||
|
b30b7bd252 | ||
|
7ce9183360 | ||
|
06af664a16 | ||
|
7adf58d35f | ||
|
08e42ed877 | ||
|
aa2fb35b41 | ||
|
ab1e762a65 | ||
|
c6201fa2fa | ||
|
0ab31fcc93 | ||
|
7616781ce9 | ||
|
a7c83b9acc | ||
|
a09649c40a | ||
|
0bb0e5b5b0 | ||
|
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 | ||
|
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 | ||
|
90b91b87ef | ||
|
bfce7cf3ad | ||
|
03a261c4c5 | ||
|
4b3558ff12 | ||
|
4355add778 | ||
|
92fbaf29d4 | ||
|
8e15dba3eb | ||
|
2206479e06 | ||
|
abeaff52e8 | ||
|
76be8d2bec | ||
|
ce27304eae | ||
|
060cf3aa3c | ||
|
f1fdf72c5b | ||
|
b580a52459 | ||
|
d13da0cdfa | ||
|
ca236d9814 | ||
|
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 | ||
|
dcd381923e | ||
|
bcf5d1b2c0 | ||
|
89dd6f7b35 | ||
|
c82e8d652a | ||
|
a9a911e77f | ||
|
e59bb3261c | ||
|
dbcb54369a | ||
|
b50a022e48 | ||
|
799db5f212 | ||
|
975976db18 | ||
|
809fa28023 | ||
|
d28359c168 | ||
|
d999558b33 | ||
|
897bfa8410 | ||
|
a3b13ed8de | ||
|
ea66b9e4f3 | ||
|
0a5827e37c | ||
|
c01d1f8c3c | ||
|
3895ce6584 | ||
|
d01f9eb27b | ||
|
325dfd285b | ||
|
d907461972 | ||
|
01a2587555 | ||
|
8b45d19b00 | ||
|
0b4b1dac44 | ||
|
f8becd3523 | ||
|
781b56f06d | ||
|
92656a68a9 | ||
|
99838a73e3 | ||
|
723156a86a | ||
|
3f6692a63b | ||
|
32e72f204a | ||
|
f5868e7f45 | ||
|
fd015de2c8 | ||
|
ec2494f2b5 | ||
|
afc7e73352 | ||
|
3519fd6a71 | ||
|
5e43f3d4ab | ||
|
337d0b8f8f | ||
|
3c7593265d | ||
|
5dcecb7f19 | ||
|
0617a441d3 | ||
|
d9abdc23d5 | ||
|
f132ec0a91 | ||
|
1797781ce8 | ||
|
88c1c849ed | ||
|
c4ac7621c2 | ||
|
bf7432deb1 | ||
|
6f74667a5c | ||
|
1e1508b74e | ||
|
da8ffa08a0 | ||
|
277dbd1054 | ||
|
43cfa0d872 | ||
|
1325ec5718 | ||
|
ecde2b5b60 | ||
|
a9f75638c6 | ||
|
a80b996f7e | ||
|
05aa6b4cf6 | ||
|
50b1d3a52e | ||
|
38b763c635 | ||
|
762b6ce607 | ||
|
0d89010ae6 | ||
|
b744f267c1 | ||
|
e840726a7d | ||
|
c53683df85 | ||
|
d9e58483ff | ||
|
9e81472d06 | ||
|
3e9cdc6b77 | ||
|
e8ac8c2602 | ||
|
eea58f4ba3 | ||
|
a95fa4a83d | ||
|
0b74d283e2 | ||
|
052e21e62d | ||
|
26f49e80e9 | ||
|
c31158a113 | ||
|
2b4fc52203 | ||
|
6222e1dfde | ||
|
077c48dea9 | ||
|
1a0b8d8dee | ||
|
66d007e703 | ||
|
81a4c5bac0 | ||
|
018157c808 | ||
|
8db97184f2 | ||
|
84948e051a | ||
|
8c20a3271e | ||
|
48c7abcfbe | ||
|
53d77f8d71 | ||
|
e8e747347a | ||
|
fee244cb08 | ||
|
2bec2bd1c4 | ||
|
1cd8098f52 | ||
|
30afcaa033 | ||
|
bdf1a57630 | ||
|
2723817832 | ||
|
22acb2abe7 | ||
|
3c616152a1 | ||
|
8cfdc613cb | ||
|
f1919934b2 | ||
|
e9da60dac3 | ||
|
0597b0997f | ||
|
6dbe30e8f7 | ||
|
d978b1cd68 | ||
|
dce356fe74 | ||
|
f965165894 | ||
|
2ac44c24a8 | ||
|
a0dc5a0d70 | ||
|
af94063bbb | ||
|
87b91b6cae | ||
|
6bdcaa9b10 | ||
|
86070d881c | ||
|
a82199967c | ||
|
f09266c081 | ||
|
563f65825f | ||
|
8bedeedfd5 | ||
|
a73cf6a71d | ||
|
1bdd6c022c | ||
|
1b553dbcaf | ||
|
5a3b4e1a0d | ||
|
1a0156b1e5 | ||
|
6ac9248262 | ||
|
70290c8f23 | ||
|
7d135b9356 | ||
|
df4629b801 | ||
|
df6f656b95 | ||
|
f27718c43b | ||
|
cbf0aaaaa4 | ||
|
2da78a94ad | ||
|
3325e08d57 | ||
|
985205e78e | ||
|
5fd5e75bd2 | ||
|
279bc15aac | ||
|
a3283b4521 | ||
|
e09c9118b2 | ||
|
330256438b | ||
|
2214f16e6e | ||
|
2237a45e76 | ||
|
f71a003904 | ||
|
10d55824f8 | ||
|
69f8bda762 | ||
|
d8de1ba353 | ||
|
d4d8718f16 | ||
|
859492ae1e | ||
|
6c08a60ce5 | ||
|
440e31fcdb |
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -52,3 +52,7 @@ updates:
|
||||
interval: "daily"
|
||||
time: "22:00"
|
||||
timezone: Africa/Abidjan
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
|
788
.github/workflows/ci.yml
vendored
788
.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@v7.0.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
|
||||
- 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
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v7.0.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.35.2
|
||||
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@v7.0.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v7.0.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
|
||||
- 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
|
||||
- name: "Init"
|
||||
run: bash ./scripts/ci/init.sh
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v7.0.0
|
||||
- uses: Alfresco/alfresco-build-tools/.github/actions/configure-git-author@v1.35.2
|
||||
with:
|
||||
username: ${{ env.GIT_USERNAME }}
|
||||
email: ${{ env.GIT_EMAIL }}
|
||||
|
@@ -1,14 +0,0 @@
|
||||
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
|
1874
.secrets.baseline
1874
.secrets.baseline
File diff suppressed because it is too large
Load Diff
@@ -3,52 +3,6 @@ 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).
|
||||
|
@@ -1,401 +0,0 @@
|
||||
<?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.2.2.4-SNAPSHOT</version>
|
||||
<version>23.3.0.80</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.2.2.4-SNAPSHOT</version>
|
||||
<version>23.3.0.80</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>23.2.2.4-SNAPSHOT</version>
|
||||
<version>23.3.0.80</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
@@ -74,6 +74,22 @@
|
||||
<artifactId>alfresco-testng</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.epam.reportportal</groupId>
|
||||
<artifactId>agent-java-testng</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<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>
|
||||
@@ -82,7 +98,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.docker-java</groupId>
|
||||
<artifactId>docker-java</artifactId>
|
||||
<version>3.3.2</version>
|
||||
<version>3.3.6</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
|
@@ -39,6 +39,7 @@ import org.alfresco.rest.rm.community.requests.gscore.GSCoreAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.ActionsExecutionAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.FilePlanAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.FilesAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.HoldsAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RMSiteAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RMUserAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RecordCategoryAPI;
|
||||
@@ -48,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;
|
||||
@@ -243,4 +245,24 @@ public class RestAPIFactory
|
||||
{
|
||||
return getGSCoreAPI(null).usingActionsExecutionsAPI();
|
||||
}
|
||||
|
||||
public HoldsAPI getHoldsAPI()
|
||||
{
|
||||
return getGSCoreAPI(null).usingHoldsAPI();
|
||||
}
|
||||
|
||||
public HoldsAPI getHoldsAPI(UserModel userModel)
|
||||
{
|
||||
return getGSCoreAPI(userModel).usingHoldsAPI();
|
||||
}
|
||||
|
||||
public RetentionScheduleAPI getRetentionScheduleAPI()
|
||||
{
|
||||
return getGSCoreAPI(null).usingRetentionScheduleAPI();
|
||||
}
|
||||
|
||||
public RetentionScheduleAPI getRetentionScheduleAPI(UserModel userModel)
|
||||
{
|
||||
return getGSCoreAPI(userModel).usingRetentionScheduleAPI();
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,6 @@ public class FilePlanComponentFields
|
||||
public static final String PROPERTIES_DECLASSIFICATION_REVIEW_COMPLETED_BY = "rma:declassificationReviewCompletedBy";
|
||||
public static final String PROPERTIES_DECLASSIFICATION_REVIEW_COMPLETED_AT = "rma:declassificationReviewCompletedAt";
|
||||
|
||||
|
||||
/** File plan properties */
|
||||
public static final String PROPERTIES_COMPONENT_ID = "st:componentId";
|
||||
public static final String PROPERTIES_COUNT = "rma:count";
|
||||
|
@@ -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,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.rest.rm.community.model.hold;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.alfresco.utility.model.TestModel;
|
||||
|
||||
/**
|
||||
* POJO for hold
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Hold extends TestModel
|
||||
{
|
||||
@JsonProperty(required = true)
|
||||
private String id;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String description;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String reason;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Hold hold = (Hold) o;
|
||||
return Objects.equals(id, hold.id) && Objects.equals(name, hold.name)
|
||||
&& Objects.equals(description, hold.description) && Objects.equals(reason, hold.reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(id, name, description, 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;
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* #%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.utility.model.TestModel;
|
||||
|
||||
/**
|
||||
* POJO for hold child
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HoldChild extends TestModel
|
||||
{
|
||||
@JsonProperty(required = true)
|
||||
private String id;
|
||||
}
|
@@ -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 HoldChildEntry}
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
public class HoldChildCollection extends RestModels<HoldChildEntry, HoldChildCollection>
|
||||
{
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* #%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;
|
||||
|
||||
/**
|
||||
* POJO for hold child entry
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HoldChildEntry extends RestModels<Hold, HoldChildEntry>
|
||||
{
|
||||
@JsonProperty
|
||||
private HoldChild entry;
|
||||
}
|
@@ -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 HoldEntry}
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
public class HoldCollection extends RestModels<HoldEntry, HoldCollection>
|
||||
{
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* #%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.utility.model.TestModel;
|
||||
|
||||
/**
|
||||
* POJO for hold deletion reason
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HoldDeletionReason extends TestModel
|
||||
{
|
||||
@JsonProperty
|
||||
private String reason;
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* #%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;
|
||||
|
||||
/**
|
||||
* POJO for hold child entry
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class HoldDeletionReasonEntry extends RestModels<HoldDeletionReason, HoldDeletionReasonEntry>
|
||||
{
|
||||
@JsonProperty
|
||||
private HoldDeletionReason entry;
|
||||
}
|
@@ -26,31 +26,27 @@
|
||||
*/
|
||||
package org.alfresco.rest.rm.community.model.hold;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.alfresco.utility.model.TestModel;
|
||||
import org.alfresco.rest.core.RestModels;
|
||||
|
||||
/**
|
||||
* POJO for hold entry
|
||||
*
|
||||
* @author Rodica Sutu
|
||||
* @since 3.2
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonIgnoreProperties (ignoreUnknown = true)
|
||||
public class HoldEntry extends TestModel
|
||||
public class HoldEntry extends RestModels<Hold, HoldEntry>
|
||||
{
|
||||
@JsonProperty (required = true)
|
||||
private String name;
|
||||
|
||||
@JsonProperty (required = true)
|
||||
private String nodeRef;
|
||||
@JsonProperty
|
||||
private Hold entry;
|
||||
}
|
||||
|
@@ -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.rest.rm.community.model.hold.v0;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.alfresco.utility.model.TestModel;
|
||||
|
||||
/**
|
||||
* POJO for hold entry
|
||||
*
|
||||
* @author Rodica Sutu
|
||||
* @since 3.2
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonIgnoreProperties (ignoreUnknown = true)
|
||||
public class HoldEntry extends TestModel
|
||||
{
|
||||
@JsonProperty (required = true)
|
||||
private String name;
|
||||
|
||||
@JsonProperty (required = true)
|
||||
private String nodeRef;
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -37,6 +37,7 @@ import org.alfresco.rest.rm.community.requests.gscore.api.ActionsExecutionAPI;
|
||||
import org.alfresco.rest.rm.community.requests.RMModelRequest;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.FilePlanAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.FilesAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.HoldsAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RMSiteAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RMUserAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RecordCategoryAPI;
|
||||
@@ -46,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
|
||||
@@ -190,4 +192,11 @@ public class GSCoreAPI extends RMModelRequest
|
||||
{
|
||||
return new ActionsExecutionAPI(getRmRestWrapper());
|
||||
}
|
||||
|
||||
public HoldsAPI usingHoldsAPI() { return new HoldsAPI(getRmRestWrapper()); }
|
||||
|
||||
public RetentionScheduleAPI usingRetentionScheduleAPI()
|
||||
{
|
||||
return new RetentionScheduleAPI(getRmRestWrapper());
|
||||
}
|
||||
}
|
||||
|
@@ -38,6 +38,8 @@ import static org.springframework.http.HttpMethod.PUT;
|
||||
|
||||
import org.alfresco.rest.core.RMRestWrapper;
|
||||
import org.alfresco.rest.rm.community.model.fileplan.FilePlan;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldCollection;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryCollection;
|
||||
import org.alfresco.rest.rm.community.requests.RMModelRequest;
|
||||
@@ -213,4 +215,74 @@ public class FilePlanAPI extends RMModelRequest
|
||||
parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hold.
|
||||
*
|
||||
* @param holdModel The hold model
|
||||
* @param filePlanId The identifier of a file plan
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The created {@link Hold}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code filePlanId} is not a valid format or {@code filePlanId} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to add children to {@code filePlanId}</li>
|
||||
* <li>{@code filePlanIds} does not exist</li>
|
||||
* <li>new name clashes with an existing node in the current parent container</li>
|
||||
* </ul>
|
||||
*/
|
||||
public Hold createHold(Hold holdModel, String filePlanId, String parameters)
|
||||
{
|
||||
mandatoryString("filePlanId", filePlanId);
|
||||
mandatoryObject("holdModel", holdModel);
|
||||
|
||||
return getRmRestWrapper().processModel(Hold.class, requestWithBody(
|
||||
POST,
|
||||
toJson(holdModel),
|
||||
"file-plans/{filePlanId}/holds",
|
||||
filePlanId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #createHold(Hold, String, String)}
|
||||
*/
|
||||
public Hold createHold(Hold holdModel, String filePlanId)
|
||||
{
|
||||
return createHold(holdModel, filePlanId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the holds of a file plan.
|
||||
*
|
||||
* @param filePlanId The identifier of a file plan
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The {@link HoldCollection} for the given {@code filePlanId}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to read {@code filePlanId}</li>
|
||||
* <li>{@code filePlanId} does not exist</li>
|
||||
*</ul>
|
||||
*/
|
||||
public HoldCollection getHolds(String filePlanId, String parameters)
|
||||
{
|
||||
mandatoryString("filePlanId", filePlanId);
|
||||
|
||||
return getRmRestWrapper().processModels(HoldCollection.class, simpleRequest(
|
||||
GET,
|
||||
"file-plans/{filePlanId}/holds?{parameters}",
|
||||
filePlanId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #getHolds(String, String)}
|
||||
*/
|
||||
public HoldCollection getHolds(String filePlanId)
|
||||
{
|
||||
return getHolds(filePlanId, EMPTY);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
* #%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 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.DELETE;
|
||||
import static org.springframework.http.HttpMethod.GET;
|
||||
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;
|
||||
import org.alfresco.rest.rm.community.requests.RMModelRequest;
|
||||
|
||||
/**
|
||||
* Holds REST API Wrapper
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
public class HoldsAPI extends RMModelRequest
|
||||
{
|
||||
|
||||
/**
|
||||
* @param rmRestWrapper
|
||||
*/
|
||||
public HoldsAPI(RMRestWrapper rmRestWrapper)
|
||||
{
|
||||
super(rmRestWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a hold.
|
||||
*
|
||||
* @param holdId The identifier of a hold
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The {@link Hold} for the given {@code holdId}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code holdId} is not a valid format</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to read {@code holdId}</li>
|
||||
* <li>{@code holdId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public Hold getHold(String holdId, String parameters)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
|
||||
return getRmRestWrapper().processModel(Hold.class, simpleRequest(
|
||||
GET,
|
||||
"holds/{holdId}?{parameters}",
|
||||
holdId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #getHold(String, String)}
|
||||
*/
|
||||
public Hold getHold(String holdId)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
|
||||
return getHold(holdId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a hold.
|
||||
*
|
||||
* @param holdModel The hold model which holds the information
|
||||
* @param holdId The identifier of the hold
|
||||
* @param parameters The URL parameters to add
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>the update request is invalid or {@code holdId} is not a valid format or {@code holdModel} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to update {@code holdId}</li>
|
||||
* <li>{@code holdId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public Hold updateHold(Hold holdModel, String holdId, String parameters)
|
||||
{
|
||||
mandatoryObject("holdModel", holdModel);
|
||||
mandatoryString("holdId", holdId);
|
||||
|
||||
return getRmRestWrapper().processModel(Hold.class, requestWithBody(
|
||||
PUT,
|
||||
toJson(holdModel),
|
||||
"holds/{holdId}?{parameters}",
|
||||
holdId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #updateHold(Hold, String, String)}
|
||||
*/
|
||||
public Hold updateHold(Hold holdModel, String holdId)
|
||||
{
|
||||
mandatoryObject("holdModel", holdModel);
|
||||
mandatoryString("holdId", holdId);
|
||||
|
||||
return updateHold(holdModel, holdId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a hold.
|
||||
*
|
||||
* @param holdId The identifier of a hold
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code holdId} is not a valid format</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to delete {@code holdId}</li>
|
||||
* <li>{@code holdId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void deleteHold(String holdId)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
|
||||
getRmRestWrapper().processEmptyModel(simpleRequest(
|
||||
DELETE,
|
||||
"holds/{holdId}",
|
||||
holdId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a hold and stores a reason for deletion in the audit log.
|
||||
*
|
||||
* @param reason The reason for hold deletion
|
||||
* @param holdId The identifier of a hold
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code holdId} is not a valid format or {@code reason} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to delete {@code holdId}</li>
|
||||
* <li>{@code holdId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public HoldDeletionReason deleteHoldWithReason(HoldDeletionReason reason, String holdId)
|
||||
{
|
||||
mandatoryObject("reason", reason);
|
||||
mandatoryString("holdId", holdId);
|
||||
|
||||
return getRmRestWrapper().processModel(HoldDeletionReason.class, requestWithBody(
|
||||
POST,
|
||||
toJson(reason),
|
||||
"holds/{holdId}/delete",
|
||||
holdId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the relationship between a child and a parent hold.
|
||||
*
|
||||
* @param holdChild The hold child model
|
||||
* @param holdId The identifier of a hold
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The created {@link Hold}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code holdId} is not a valid format or {@code holdId} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to add children to {@code holdId}</li>
|
||||
* <li>{@code holdId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public HoldChild addChildToHold(HoldChild holdChild, String holdId, String parameters)
|
||||
{
|
||||
mandatoryObject("holdId", holdId);
|
||||
|
||||
return getRmRestWrapper().processModel(HoldChild.class, requestWithBody(
|
||||
POST,
|
||||
toJson(holdChild),
|
||||
"holds/{holdId}/children",
|
||||
holdId,
|
||||
parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #addChildToHold(HoldChild, String, String)}
|
||||
*/
|
||||
public HoldChild addChildToHold(HoldChild holdChild, String holdId)
|
||||
{
|
||||
return addChildToHold(holdChild, holdId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the children of a hold.
|
||||
*
|
||||
* @param holdId The identifier of a hold
|
||||
* @param parameters The URL parameters to add
|
||||
* @return The {@link HoldChildCollection} for the given {@code holdId}
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to read {@code holdId}</li>
|
||||
* <li>{@code holdId} does not exist</li>
|
||||
*</ul>
|
||||
*/
|
||||
public HoldChildCollection getChildren(String holdId, String parameters)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
|
||||
return getRmRestWrapper().processModels(HoldChildCollection.class, simpleRequest(
|
||||
GET,
|
||||
"holds/{holdId}/children",
|
||||
holdId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #getChildren(String, String)}
|
||||
*/
|
||||
public HoldChildCollection getChildren(String holdId)
|
||||
{
|
||||
return getChildren(holdId, EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the relationship between a child and a parent hold.
|
||||
*
|
||||
* @param holdChildId The identifier of hold child
|
||||
* @param holdId The identifier of a hold
|
||||
* @param parameters The URL parameters to add
|
||||
* @throws RuntimeException for the following cases:
|
||||
* <ul>
|
||||
* <li>{@code holdId} or {@code holdChildId} is invalid</li>
|
||||
* <li>authentication fails</li>
|
||||
* <li>current user does not have permission to delete children from {@code holdId}</li>
|
||||
* <li>{@code holdId} does not exist</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void deleteHoldChild(String holdId, String holdChildId, String parameters)
|
||||
{
|
||||
mandatoryString("holdId", holdId);
|
||||
mandatoryString("holdChildId", holdChildId);
|
||||
|
||||
getRmRestWrapper().processEmptyModel(simpleRequest(
|
||||
DELETE,
|
||||
"holds/{holdId}/children/{holdChildId}",
|
||||
holdId,
|
||||
holdChildId,
|
||||
parameters
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #deleteHoldChild(String, String, String)}
|
||||
*/
|
||||
public void deleteHoldChild(String holdId, String holdChildId)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
@@ -36,7 +36,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.rest.core.v0.APIUtils;
|
||||
import org.alfresco.rest.core.v0.BaseAPI;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.v0.HoldEntry;
|
||||
import org.alfresco.rest.rm.community.util.PojoUtility;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.apache.http.HttpResponse;
|
||||
|
@@ -31,18 +31,18 @@ import static java.util.Arrays.asList;
|
||||
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.audit.AuditEvents.ADD_TO_HOLD;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.rest.rm.community.utils.RMSiteUtil.FILE_PLAN_PATH;
|
||||
import static org.alfresco.utility.Utility.buildPath;
|
||||
import static org.alfresco.utility.Utility.removeLastSlash;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
import static org.testng.AssertJUnit.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -50,12 +50,13 @@ import com.google.common.collect.ImmutableMap;
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChild;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.rm.community.model.user.UserPermissions;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.v0.HoldsAPI;
|
||||
import org.alfresco.rest.v0.service.RMAuditService;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
@@ -85,8 +86,6 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
@Autowired
|
||||
private RMAuditService rmAuditService;
|
||||
@Autowired
|
||||
private HoldsAPI holdsAPI;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
private UserModel rmAdmin, rmManagerNoReadOnHold, rmManagerNoReadOnNode;
|
||||
@@ -94,17 +93,22 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
private RecordCategory recordCategory;
|
||||
private RecordCategoryChild recordFolder;
|
||||
private List<AuditEntry> auditEntries;
|
||||
private final List<String> holdsList = asList(HOLD1, HOLD2);
|
||||
private List<String> holdsListRef = new ArrayList<>();
|
||||
private String hold1NodeRef;
|
||||
private String hold2NodeRef;
|
||||
|
||||
@BeforeClass (alwaysRun = true)
|
||||
public void preconditionForAuditAddToHoldTests()
|
||||
{
|
||||
STEP("Create 2 holds.");
|
||||
hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(),
|
||||
getAdminUser().getPassword(), HOLD1, HOLD_REASON, HOLD_DESCRIPTION);
|
||||
String hold2NodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD2, HOLD_REASON, HOLD_DESCRIPTION);
|
||||
hold1NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD1).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
hold2NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD2).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
holdsListRef = asList(hold1NodeRef, hold2NodeRef);
|
||||
|
||||
STEP("Create a new record category with a record folder.");
|
||||
@@ -169,7 +173,8 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Add node to hold.");
|
||||
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), nodeId, HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(nodeId).build(), hold1NodeRef);
|
||||
|
||||
|
||||
STEP("Check the audit log contains the entry for the add to hold event.");
|
||||
rmAuditService.checkAuditLogForEvent(getAdminUser(), ADD_TO_HOLD, rmAdmin, nodeName, nodePath,
|
||||
@@ -191,9 +196,8 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Try to add the record to a hold by an user with no rights.");
|
||||
holdsAPI.addItemsToHolds(rmManagerNoReadOnHold.getUsername(), rmManagerNoReadOnHold.getPassword(),
|
||||
SC_INTERNAL_SERVER_ERROR, Collections.singletonList(recordToBeAdded.getId()),
|
||||
Collections.singletonList(hold1NodeRef));
|
||||
getRestAPIFactory().getHoldsAPI(rmManagerNoReadOnHold).addChildToHold(HoldChild.builder().id(recordToBeAdded.getId()).build(), hold1NodeRef);
|
||||
assertStatusCode(FORBIDDEN);
|
||||
|
||||
STEP("Check the audit log doesn't contain the entry for the unsuccessful add to hold.");
|
||||
assertTrue("The list of events should not contain Add to Hold entry ",
|
||||
@@ -215,7 +219,7 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Add record folder to hold.");
|
||||
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), notEmptyRecFolder.getId(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(notEmptyRecFolder.getId()).build(), hold1NodeRef);
|
||||
|
||||
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), ADD_TO_HOLD);
|
||||
|
||||
@@ -239,8 +243,9 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Add record to multiple holds.");
|
||||
holdsAPI.addItemsToHolds(rmAdmin.getUsername(), rmAdmin.getPassword(),
|
||||
Collections.singletonList(recordToBeAdded.getId()), holdsList);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(recordToBeAdded.getId()).build(), hold1NodeRef);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(recordToBeAdded.getId()).build(), hold2NodeRef);
|
||||
|
||||
|
||||
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), ADD_TO_HOLD);
|
||||
|
||||
@@ -268,7 +273,7 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Add file to hold.");
|
||||
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), contentToBeAdded.getNodeRefWithoutVersion(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(contentToBeAdded.getNodeRefWithoutVersion()).build(), hold1NodeRef);
|
||||
|
||||
STEP("Check that an user with no Read permissions can't see the entry for the add to hold event.");
|
||||
assertTrue("The list of events should not contain Add to Hold entry ",
|
||||
@@ -289,7 +294,7 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Add file to hold.");
|
||||
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), contentToBeAdded.getNodeRefWithoutVersion(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(contentToBeAdded.getNodeRefWithoutVersion()).build(), hold1NodeRef);
|
||||
|
||||
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(rmManagerNoReadOnHold, ADD_TO_HOLD);
|
||||
|
||||
@@ -304,7 +309,8 @@ public class AuditAddToHoldTests extends BaseRMRestTest
|
||||
@AfterClass (alwaysRun = true)
|
||||
public void cleanUpAuditAddToHoldTests()
|
||||
{
|
||||
holdsListRef.forEach(holdRef -> holdsAPI.deleteHold(getAdminUser(), holdRef));
|
||||
holdsListRef.forEach(holdRef -> getRestAPIFactory().getHoldsAPI(getAdminUser()).deleteHold(holdRef));
|
||||
|
||||
dataSite.usingAdmin().deleteSite(privateSite);
|
||||
asList(rmAdmin, rmManagerNoReadOnHold, rmManagerNoReadOnNode).forEach(user -> getDataUser().usingAdmin().deleteUser(user));
|
||||
deleteRecordCategory(recordCategory.getId());
|
||||
|
@@ -31,9 +31,10 @@ import static java.util.Arrays.asList;
|
||||
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.audit.AuditEvents.CREATE_HOLD;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
||||
import static org.springframework.http.HttpStatus.CONFLICT;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
import static org.testng.AssertJUnit.assertTrue;
|
||||
|
||||
@@ -44,8 +45,8 @@ import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.v0.HoldsAPI;
|
||||
import org.alfresco.rest.v0.service.RMAuditService;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
@@ -73,8 +74,6 @@ public class AuditCreateHoldTests extends BaseRMRestTest
|
||||
@Autowired
|
||||
private RMAuditService rmAuditService;
|
||||
@Autowired
|
||||
private HoldsAPI holdsAPI;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
private UserModel rmAdmin, rmManager;
|
||||
@@ -102,8 +101,10 @@ public class AuditCreateHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Create a new hold.");
|
||||
String hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD1,
|
||||
HOLD_REASON, HOLD_DESCRIPTION);
|
||||
String hold1NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD1).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
holdsListRef.add(hold1NodeRef);
|
||||
STEP("Check the audit log contains the entry for the created hold with the hold details.");
|
||||
rmAuditService.checkAuditLogForEvent(getAdminUser(), CREATE_HOLD, rmAdmin, HOLD1,
|
||||
@@ -120,13 +121,18 @@ public class AuditCreateHoldTests extends BaseRMRestTest
|
||||
public void createHoldEventIsNotAuditedForExistingHold()
|
||||
{
|
||||
STEP("Create a new hold.");
|
||||
String hold2NodeRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD2, HOLD_REASON, HOLD_DESCRIPTION);
|
||||
String hold2NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD2).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
holdsListRef.add(hold2NodeRef);
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Try to create again the same hold and expect action to fail.");
|
||||
holdsAPI.createHold(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD2, HOLD_REASON, HOLD_DESCRIPTION,
|
||||
SC_INTERNAL_SERVER_ERROR);
|
||||
getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD2).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS);
|
||||
assertStatusCode(CONFLICT);
|
||||
|
||||
STEP("Check the audit log doesn't contain the entry for the second create hold event.");
|
||||
assertTrue("The list of events should not contain Create Hold entry ",
|
||||
@@ -145,13 +151,17 @@ public class AuditCreateHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Create a new hold.");
|
||||
holdsAPI.createHold(rmAdmin.getUsername(), rmAdmin.getPassword(), holdName, HOLD_REASON, HOLD_DESCRIPTION);
|
||||
String nodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(holdName).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS).getId();
|
||||
|
||||
STEP("Get the list of audit entries for the create hold event.");
|
||||
List<AuditEntry> auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), CREATE_HOLD);
|
||||
|
||||
STEP("Delete the created hold.");
|
||||
holdsAPI.deleteHold(rmAdmin.getUsername(), rmAdmin.getPassword(), holdName);
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(rmAdmin)
|
||||
.deleteHold(nodeRef);
|
||||
|
||||
STEP("Get again the list of audit entries for the create hold event.");
|
||||
List<AuditEntry> auditEntriesAfterDelete = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), CREATE_HOLD);
|
||||
@@ -171,8 +181,10 @@ public class AuditCreateHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Create a new hold.");
|
||||
String hold3NodeRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD3,
|
||||
HOLD_REASON, HOLD_DESCRIPTION);
|
||||
String hold3NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD3).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS).getId();
|
||||
|
||||
holdsListRef.add(hold3NodeRef);
|
||||
|
||||
STEP("Check that an user with no Read permissions over the hold can't see the entry for the create hold event");
|
||||
@@ -183,7 +195,7 @@ public class AuditCreateHoldTests extends BaseRMRestTest
|
||||
@AfterClass (alwaysRun = true)
|
||||
public void cleanUpAuditCreateHoldTests()
|
||||
{
|
||||
holdsListRef.forEach(holdRef -> holdsAPI.deleteHold(getAdminUser(), holdRef));
|
||||
holdsListRef.forEach(holdRef -> getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHold(holdRef));
|
||||
asList(rmAdmin, rmManager).forEach(user -> getDataUser().usingAdmin().deleteUser(user));
|
||||
}
|
||||
}
|
||||
|
@@ -31,18 +31,20 @@ import static java.util.Arrays.asList;
|
||||
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.audit.AuditEvents.DELETE_HOLD;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.testng.AssertJUnit.assertTrue;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldDeletionReason;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.v0.HoldsAPI;
|
||||
import org.alfresco.rest.v0.service.RMAuditService;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
@@ -62,14 +64,13 @@ import org.testng.annotations.Test;
|
||||
public class AuditDeleteHoldTests extends BaseRMRestTest
|
||||
{
|
||||
private final String PREFIX = generateTestPrefix(AuditDeleteHoldTests.class);
|
||||
private final String HOLD = PREFIX + "holdToBeDeleted";
|
||||
private final String HOLD2 = PREFIX + "deleteHold";
|
||||
private final String hold = PREFIX + "holdToBeDeleted";
|
||||
private final String hold2 = PREFIX + "deleteHold";
|
||||
private final String hold3 = PREFIX + "deleteHoldWithReason";
|
||||
|
||||
@Autowired
|
||||
private RMAuditService rmAuditService;
|
||||
@Autowired
|
||||
private HoldsAPI holdsAPI;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
private UserModel rmAdmin, rmManager;
|
||||
@@ -79,8 +80,10 @@ public class AuditDeleteHoldTests extends BaseRMRestTest
|
||||
public void preconditionForAuditDeleteHoldTests()
|
||||
{
|
||||
STEP("Create a new hold.");
|
||||
holdNodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD,
|
||||
HOLD_REASON, HOLD_DESCRIPTION);
|
||||
holdNodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(hold).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
|
||||
STEP("Create 2 users with different permissions for the created hold.");
|
||||
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
|
||||
@@ -99,17 +102,51 @@ public class AuditDeleteHoldTests extends BaseRMRestTest
|
||||
public void deleteHoldEventIsAudited()
|
||||
{
|
||||
STEP("Create a new hold.");
|
||||
String holdRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD2,
|
||||
HOLD_REASON, HOLD_DESCRIPTION);
|
||||
String holdRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(hold2).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Delete the created hold.");
|
||||
holdsAPI.deleteHold(rmAdmin, holdRef);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHold(holdRef);
|
||||
|
||||
STEP("Check the audit log contains the entry for the deleted hold with the hold details.");
|
||||
rmAuditService.checkAuditLogForEvent(getAdminUser(), DELETE_HOLD, rmAdmin, HOLD2,
|
||||
Collections.singletonList(ImmutableMap.of("new", "", "previous", HOLD2, "name", "Hold Name")));
|
||||
rmAuditService.checkAuditLogForEvent(getAdminUser(), DELETE_HOLD, rmAdmin, hold2,
|
||||
List.of(ImmutableMap.of("new", "", "previous", hold2, "name", "Hold Name"),
|
||||
ImmutableMap.of("new", "", "previous", "", "name", "Hold deletion reason")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a hold is deleted with a reason
|
||||
* When I view the audit log
|
||||
* Then an entry has been created in the audit log which contains the following:
|
||||
* name of the hold
|
||||
* hold deletion reason
|
||||
* user who deleted the hold
|
||||
* date the delete occurred
|
||||
*/
|
||||
@Test
|
||||
public void deleteHoldWithReasonEventIsAudited()
|
||||
{
|
||||
STEP("Create a new hold.");
|
||||
String holdRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(hold3).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
|
||||
String deletionReason = "Test reason";
|
||||
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Delete the created hold with a reason.");
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHoldWithReason(HoldDeletionReason.builder().reason(deletionReason).build(), holdRef);
|
||||
|
||||
STEP("Check the audit log contains the entry for the deleted hold with the hold details.");
|
||||
rmAuditService.checkAuditLogForEvent(getAdminUser(), DELETE_HOLD, rmAdmin, hold3,
|
||||
List.of(ImmutableMap.of("new", "", "previous", hold3, "name", "Hold Name"),
|
||||
ImmutableMap.of("new", "", "previous", deletionReason, "name", "Hold deletion reason")));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,7 +160,8 @@ public class AuditDeleteHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Try to delete a hold by an user with no Read permissions over the hold.");
|
||||
holdsAPI.deleteHold(rmManager.getUsername(), rmManager.getPassword(), holdNodeRef, SC_INTERNAL_SERVER_ERROR);
|
||||
getRestAPIFactory().getHoldsAPI(rmManager).deleteHold(holdNodeRef);
|
||||
assertStatusCode(FORBIDDEN);
|
||||
|
||||
STEP("Check the audit log doesn't contain the entry for the unsuccessful delete hold.");
|
||||
assertTrue("The list of events should not contain Delete Hold entry ",
|
||||
@@ -133,7 +171,7 @@ public class AuditDeleteHoldTests extends BaseRMRestTest
|
||||
@AfterClass (alwaysRun = true)
|
||||
public void cleanUpAuditDeleteHoldTests()
|
||||
{
|
||||
holdsAPI.deleteHold(getAdminUser(), holdNodeRef);
|
||||
getRestAPIFactory().getHoldsAPI(rmManager).deleteHold(holdNodeRef);
|
||||
asList(rmAdmin, rmManager).forEach(user -> getDataUser().usingAdmin().deleteUser(user));
|
||||
}
|
||||
}
|
||||
|
@@ -25,10 +25,14 @@
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.rest.rm.community.audit;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.alfresco.rest.rm.community.base.TestData.*;
|
||||
|
||||
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.audit.AuditEvents.ADD_TO_HOLD;
|
||||
import static org.alfresco.rest.rm.community.model.audit.AuditEvents.REMOVE_FROM_HOLD;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
@@ -37,20 +41,22 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.testng.AssertJUnit.*;
|
||||
import static org.testng.AssertJUnit.assertFalse;
|
||||
import static org.testng.AssertJUnit.assertTrue;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
|
||||
import org.alfresco.rest.rm.community.model.audit.AuditEvents;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChild;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.rm.community.model.recordfolder.RecordFolder;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.v0.HoldsAPI;
|
||||
import org.alfresco.rest.v0.service.RMAuditService;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
@@ -69,8 +75,6 @@ public class AuditHoldsTest extends BaseRMRestTest {
|
||||
@Autowired
|
||||
private RMAuditService rmAuditService;
|
||||
@Autowired
|
||||
private HoldsAPI holdsAPI;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
private UserModel rmAdmin;
|
||||
private RecordCategory recordCategory;
|
||||
@@ -85,8 +89,11 @@ public class AuditHoldsTest extends BaseRMRestTest {
|
||||
rmAdmin = roleService.createUserWithRMRole(UserRoles.ROLE_RM_ADMIN.roleId);
|
||||
|
||||
STEP("Create a hold");
|
||||
hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(rmAdmin.getUsername(), rmAdmin.getPassword(), HOLD1, HOLD_REASON,
|
||||
HOLD_DESCRIPTION);
|
||||
|
||||
hold1NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD1).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
|
||||
STEP("Create a collaboration site with a test file.");
|
||||
publicSite = dataSite.usingAdmin().createPublicRandomSite();
|
||||
@@ -101,9 +108,11 @@ public class AuditHoldsTest extends BaseRMRestTest {
|
||||
|
||||
STEP("Add some items to the hold, then remove them from the hold");
|
||||
final List<String> itemsList = asList(testFile.getNodeRefWithoutVersion(), recordToBeAdded.getId(), recordFolder2.getId());
|
||||
final List<String> holdsList = Collections.singletonList(HOLD1);
|
||||
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), recordToBeAdded.getId(), HOLD1);
|
||||
holdsAPI.removeItemsFromHolds(rmAdmin.getUsername(), rmAdmin.getPassword(), itemsList, holdsList);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(recordToBeAdded.getId()).build(), hold1NodeRef);
|
||||
for(String childId : itemsList)
|
||||
{
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHoldChild(hold1NodeRef, childId);
|
||||
}
|
||||
|
||||
STEP("Delete the record folder that was held");
|
||||
getRestAPIFactory().getRecordFolderAPI().deleteRecordFolder(recordFolder2.getId());
|
||||
|
@@ -31,18 +31,18 @@ import static java.util.Arrays.asList;
|
||||
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.audit.AuditEvents.REMOVE_FROM_HOLD;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.rest.rm.community.utils.RMSiteUtil.FILE_PLAN_PATH;
|
||||
import static org.alfresco.utility.Utility.buildPath;
|
||||
import static org.alfresco.utility.Utility.removeLastSlash;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
import static org.testng.AssertJUnit.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
@@ -50,12 +50,13 @@ import com.google.common.collect.ImmutableMap;
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.audit.AuditEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChild;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.rm.community.model.user.UserPermissions;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.v0.HoldsAPI;
|
||||
import org.alfresco.rest.v0.service.RMAuditService;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.test.AlfrescoTest;
|
||||
@@ -86,8 +87,6 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
@Autowired
|
||||
private RMAuditService rmAuditService;
|
||||
@Autowired
|
||||
private HoldsAPI holdsAPI;
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
private UserModel rmAdmin, rmManagerNoReadOnHold, rmManagerNoReadOnNode;
|
||||
@@ -96,10 +95,11 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
private RecordCategoryChild recordFolder, heldRecordFolder;
|
||||
private Record heldRecord;
|
||||
private List<AuditEntry> auditEntries;
|
||||
private final List<String> holdsList = asList(HOLD1, HOLD2, HOLD3);
|
||||
private List<String> holdsListRef = new ArrayList<>();
|
||||
private FileModel heldContent;
|
||||
private String hold1NodeRef;
|
||||
private String hold2NodeRef;
|
||||
private String hold3NodeRef;
|
||||
|
||||
@BeforeClass (alwaysRun = true)
|
||||
public void preconditionForAuditRemoveFromHoldTests()
|
||||
@@ -111,10 +111,18 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
privateSite = dataSite.usingUser(rmAdmin).createPrivateRandomSite();
|
||||
|
||||
STEP("Create new holds.");
|
||||
hold1NodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getPassword(),
|
||||
HOLD1, HOLD_REASON, HOLD_DESCRIPTION);
|
||||
String hold2NodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD2, HOLD_REASON, HOLD_DESCRIPTION);
|
||||
String hold3NodeRef = holdsAPI.createHoldAndGetNodeRef(getAdminUser().getUsername(), getAdminUser().getPassword(), HOLD3, HOLD_REASON, HOLD_DESCRIPTION);
|
||||
hold1NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD1).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
hold2NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD2).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
hold3NodeRef = getRestAPIFactory()
|
||||
.getFilePlansAPI(rmAdmin)
|
||||
.createHold(Hold.builder().name(HOLD3).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), FILE_PLAN_ALIAS)
|
||||
.getId();
|
||||
holdsListRef = asList(hold1NodeRef, hold2NodeRef, hold3NodeRef);
|
||||
|
||||
STEP("Create a new record category with a record folder.");
|
||||
@@ -127,9 +135,12 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
heldRecordFolder = createRecordFolder(recordCategory.getId(), PREFIX + "heldRecFolder");
|
||||
heldRecord = createElectronicRecord(recordFolder.getId(), PREFIX + "record");
|
||||
|
||||
holdsAPI.addItemsToHolds(getAdminUser().getUsername(), getAdminUser().getPassword(),
|
||||
asList(heldContent.getNodeRefWithoutVersion(), heldRecordFolder.getId(), heldRecord.getId()),
|
||||
holdsList);
|
||||
holdsListRef.forEach(holdRef ->
|
||||
{
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(heldContent.getNodeRefWithoutVersion()).build(), holdRef);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(heldRecordFolder.getId()).build(), holdRef);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(heldRecord.getId()).build(), holdRef);
|
||||
});
|
||||
|
||||
STEP("Create users without rights to remove content from a hold.");
|
||||
rmManagerNoReadOnHold = roleService.createUserWithSiteRoleRMRoleAndPermission(privateSite,
|
||||
@@ -179,7 +190,7 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Remove node from hold.");
|
||||
holdsAPI.removeItemFromHold(rmAdmin.getUsername(), rmAdmin.getPassword(), nodeId, HOLD3);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHoldChild(hold3NodeRef, nodeId);
|
||||
|
||||
STEP("Check the audit log contains the entry for the remove from hold event.");
|
||||
rmAuditService.checkAuditLogForEvent(getAdminUser(), REMOVE_FROM_HOLD, rmAdmin, nodeName, nodePath,
|
||||
@@ -198,9 +209,8 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Try to remove the record from a hold by an user with no rights.");
|
||||
holdsAPI.removeItemsFromHolds(rmManagerNoReadOnHold.getUsername(), rmManagerNoReadOnHold.getPassword(),
|
||||
SC_INTERNAL_SERVER_ERROR, Collections.singletonList(heldRecord.getId()),
|
||||
Collections.singletonList(hold1NodeRef));
|
||||
getRestAPIFactory().getHoldsAPI(rmManagerNoReadOnHold).deleteHoldChild(hold1NodeRef, heldRecord.getId());
|
||||
assertStatusCode(FORBIDDEN);
|
||||
|
||||
STEP("Check the audit log doesn't contain the entry for the unsuccessful remove from hold.");
|
||||
assertTrue("The list of events should not contain remove from hold entry ",
|
||||
@@ -220,12 +230,12 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
Record record = createElectronicRecord(notEmptyRecFolder.getId(), PREFIX + "record");
|
||||
|
||||
STEP("Add the record folder to a hold.");
|
||||
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), notEmptyRecFolder.getId(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(notEmptyRecFolder.getId()).build(), hold1NodeRef);
|
||||
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Remove record folder from hold.");
|
||||
holdsAPI.removeItemFromHold(rmAdmin.getUsername(), rmAdmin.getPassword(), notEmptyRecFolder.getId(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHoldChild(hold1NodeRef, notEmptyRecFolder.getId());
|
||||
|
||||
STEP("Get the list of audit entries for the remove from hold event.");
|
||||
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), REMOVE_FROM_HOLD);
|
||||
@@ -247,8 +257,8 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Remove record folder from multiple holds.");
|
||||
holdsAPI.removeItemsFromHolds(rmAdmin.getUsername(), rmAdmin.getPassword(),
|
||||
Collections.singletonList(heldRecordFolder.getId()), asList(HOLD1, HOLD2));
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHoldChild(hold1NodeRef, heldRecordFolder.getId());
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHoldChild(hold2NodeRef, heldRecordFolder.getId());
|
||||
|
||||
STEP("Get the list of audit entries for the remove from hold event.");
|
||||
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(getAdminUser(), REMOVE_FROM_HOLD);
|
||||
@@ -275,12 +285,12 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
STEP("Add content to a hold.");
|
||||
FileModel heldFile = dataContent.usingAdmin().usingSite(privateSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), heldFile.getNodeRefWithoutVersion(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(heldFile.getNodeRefWithoutVersion()).build(), hold1NodeRef);
|
||||
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Remove held content from the hold.");
|
||||
holdsAPI.removeItemFromHold(rmAdmin.getUsername(), rmAdmin.getPassword(), heldFile.getNodeRefWithoutVersion(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHoldChild(hold1NodeRef, heldFile.getNodeRefWithoutVersion());
|
||||
|
||||
STEP("Check that an user with no Read permissions can't see the entry for the remove from hold event.");
|
||||
assertTrue("The list of events should not contain Remove from Hold entry ",
|
||||
@@ -298,12 +308,12 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
STEP("Add content to a hold.");
|
||||
FileModel heldFile = dataContent.usingAdmin().usingSite(privateSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
holdsAPI.addItemToHold(rmAdmin.getUsername(), rmAdmin.getPassword(), heldFile.getNodeRefWithoutVersion(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).addChildToHold(HoldChild.builder().id(heldFile.getNodeRefWithoutVersion()).build(), hold1NodeRef);
|
||||
|
||||
rmAuditService.clearAuditLog();
|
||||
|
||||
STEP("Remove held content from the hold.");
|
||||
holdsAPI.removeItemFromHold(rmAdmin.getUsername(), rmAdmin.getPassword(), heldFile.getNodeRefWithoutVersion(), HOLD1);
|
||||
getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHoldChild(hold1NodeRef, heldFile.getNodeRefWithoutVersion());
|
||||
|
||||
auditEntries = rmAuditService.getAuditEntriesFilteredByEvent(rmManagerNoReadOnHold, REMOVE_FROM_HOLD);
|
||||
|
||||
@@ -318,7 +328,7 @@ public class AuditRemoveFromHoldTests extends BaseRMRestTest
|
||||
@AfterClass (alwaysRun = true)
|
||||
public void cleanUpAuditRemoveFromHoldTests()
|
||||
{
|
||||
holdsListRef.forEach(holdRef -> holdsAPI.deleteHold(getAdminUser(), holdRef));
|
||||
holdsListRef.forEach(holdRef -> getRestAPIFactory().getHoldsAPI(rmAdmin).deleteHold(holdRef));
|
||||
dataSite.usingAdmin().deleteSite(privateSite);
|
||||
asList(rmAdmin, rmManagerNoReadOnHold, rmManagerNoReadOnNode).forEach(user -> getDataUser().usingAdmin().deleteUser(user));
|
||||
deleteRecordCategory(recordCategory.getId());
|
||||
|
@@ -60,12 +60,15 @@ import static org.testng.Assert.fail;
|
||||
import static org.testng.AssertJUnit.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.base.DataProviderClass;
|
||||
import org.alfresco.rest.rm.community.model.fileplan.FilePlan;
|
||||
import org.alfresco.rest.rm.community.model.fileplan.FilePlanProperties;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldCollection;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryCollection;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryProperties;
|
||||
@@ -514,5 +517,97 @@ public class FilePlanTests extends BaseRMRestTest
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Given that a file plan exists
|
||||
* When I ask the API to create a hold
|
||||
* Then it is created
|
||||
* </pre>
|
||||
*/
|
||||
@Test
|
||||
public void createHolds()
|
||||
{
|
||||
String holdName = "Hold" + getRandomAlphanumeric();
|
||||
String holdDescription = "Description" + getRandomAlphanumeric();
|
||||
String holdReason = "Reason" + getRandomAlphanumeric();
|
||||
|
||||
// Create the hold
|
||||
Hold hold = Hold.builder()
|
||||
.name(holdName)
|
||||
.description(holdDescription)
|
||||
.reason(holdReason)
|
||||
.build();
|
||||
Hold createdHold = getRestAPIFactory().getFilePlansAPI()
|
||||
.createHold(hold, FILE_PLAN_ALIAS);
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
assertEquals(createdHold.getName(), holdName);
|
||||
assertEquals(createdHold.getDescription(), holdDescription);
|
||||
assertEquals(createdHold.getReason(), holdReason);
|
||||
assertNotNull(createdHold.getId());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void listHolds()
|
||||
{
|
||||
// Delete all holds
|
||||
getRestAPIFactory().getFilePlansAPI().getHolds(FILE_PLAN_ALIAS).getEntries().forEach(holdEntry ->
|
||||
getRestAPIFactory().getHoldsAPI().deleteHold(holdEntry.getEntry().getId()));
|
||||
|
||||
// Add holds
|
||||
List<Hold> filePlanHolds = new ArrayList<>();
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++)
|
||||
{
|
||||
String holdName = "Hold name " + getRandomAlphanumeric();
|
||||
String holdDescription = "Hold Description " + getRandomAlphanumeric();
|
||||
String holdReason = "Reason " + getRandomAlphanumeric();
|
||||
// Create a hold
|
||||
Hold hold = Hold.builder()
|
||||
.name(holdName)
|
||||
.description(holdDescription)
|
||||
.reason(holdReason)
|
||||
.build();
|
||||
Hold createdHold = getRestAPIFactory().getFilePlansAPI()
|
||||
.createHold(hold, FILE_PLAN_ALIAS);
|
||||
assertNotNull(createdHold.getId());
|
||||
filePlanHolds.add(createdHold);
|
||||
}
|
||||
|
||||
// Get holds of a file plan
|
||||
HoldCollection holdCollection = getRestAPIFactory().getFilePlansAPI()
|
||||
.getHolds(FILE_PLAN_ALIAS);
|
||||
|
||||
// Check status code
|
||||
assertStatusCode(OK);
|
||||
|
||||
// Check holds against created list
|
||||
holdCollection.getEntries().forEach(c ->
|
||||
{
|
||||
Hold hold = c.getEntry();
|
||||
String holdId = hold.getId();
|
||||
assertNotNull(holdId);
|
||||
logger.info("Checking hold " + holdId);
|
||||
|
||||
try
|
||||
{
|
||||
// Find this hold in created holds list
|
||||
Hold createdHold = filePlanHolds.stream()
|
||||
.filter(child -> child.getId().equals(holdId))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
|
||||
assertEquals(createdHold.getName(), hold.getName());
|
||||
assertEquals(createdHold.getDescription(), hold.getDescription());
|
||||
assertEquals(createdHold.getReason(), hold.getReason());
|
||||
}
|
||||
catch (NoSuchElementException e)
|
||||
{
|
||||
fail("No child element for " + hold);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -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()));
|
||||
}
|
||||
}
|
@@ -60,7 +60,7 @@ import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.dataprep.ContentActions;
|
||||
import org.alfresco.rest.model.RestNodeModel;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.v0.HoldEntry;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
|
@@ -0,0 +1,386 @@
|
||||
/*-
|
||||
* #%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.fileplancomponents.FilePlanComponentAlias.TRANSFERS_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAlias.UNFILED_RECORDS_CONTAINER_ALIAS;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.FROZEN_ASPECT;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentType.UNFILED_RECORD_FOLDER_TYPE;
|
||||
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.model.user.UserRoles.ROLE_RM_MANAGER;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.rest.rm.community.utils.CoreUtil.toContentModel;
|
||||
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.IMAGE_FILE;
|
||||
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createElectronicRecordModel;
|
||||
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createNonElectronicRecordModel;
|
||||
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.getFile;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.apache.commons.httpclient.HttpStatus.SC_BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.AssertJUnit.assertFalse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.dataprep.ContentActions;
|
||||
import org.alfresco.rest.model.RestNodeAssociationModelCollection;
|
||||
import org.alfresco.rest.model.RestNodeModel;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChild;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.FilePlanAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
import org.alfresco.utility.model.UserModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* V1 API tests for adding content/record folder/records to holds
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
public class AddToHoldsV1Tests 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 String INVALID_TYPE_ERROR_MESSAGE = "Only records, record folders or content can be added to a hold.";
|
||||
private static final String LOCKED_FILE_ERROR_MESSAGE = "Locked content can't be added to a hold.";
|
||||
|
||||
private static final String HOLD = "HOLD" + generateTestPrefix(AddToHoldsV1Tests.class);
|
||||
private String holdNodeRef;
|
||||
private SiteModel testSite;
|
||||
private FileModel documentHeld;
|
||||
private FileModel contentToAddToHold;
|
||||
private FileModel contentAddToHoldNoPermission;
|
||||
private Hold hold;
|
||||
|
||||
private UserModel userAddHoldPermission;
|
||||
private final List<UserModel> users = new ArrayList<>();
|
||||
private final List<String> nodesToBeClean = new ArrayList<>();
|
||||
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
@Autowired
|
||||
private ContentActions contentActions;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void preconditionForAddContentToHold()
|
||||
{
|
||||
STEP("Create a hold.");
|
||||
hold = createHold(FILE_PLAN_ALIAS,
|
||||
Hold.builder().name(HOLD).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), getAdminUser());
|
||||
holdNodeRef = hold.getId();
|
||||
STEP("Create test files.");
|
||||
testSite = dataSite.usingAdmin().createPublicRandomSite();
|
||||
documentHeld = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
contentToAddToHold = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
contentAddToHoldNoPermission = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
STEP("Add the content to the hold.");
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(documentHeld.getNodeRefWithoutVersion()).build(), hold.getId());
|
||||
|
||||
STEP("Create users");
|
||||
userAddHoldPermission = roleService.createUserWithSiteRoleRMRoleAndPermission(testSite,
|
||||
UserRole.SiteCollaborator, holdNodeRef, UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING);
|
||||
users.add(userAddHoldPermission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a hold that contains at least one active content
|
||||
* When I use the existing REST API to retrieve the contents of the hold
|
||||
* Then I should see all the active content on hold
|
||||
*/
|
||||
@Test
|
||||
public void retrieveTheContentOfTheHoldUsingV1API()
|
||||
{
|
||||
STEP("Retrieve the list of children from the hold and collect the entries that have the name of the active " +
|
||||
"content held");
|
||||
List<String> documentNames = restClient.authenticateUser(getAdminUser()).withCoreAPI()
|
||||
.usingNode(toContentModel(holdNodeRef))
|
||||
.listChildren().getEntries().stream()
|
||||
.map(RestNodeModel::onModel)
|
||||
.map(RestNodeModel::getName)
|
||||
.filter(documentName -> documentName.equals(documentHeld.getName()))
|
||||
.toList();
|
||||
|
||||
STEP("Check the list of active content");
|
||||
assertEquals(documentNames, Set.of(documentHeld.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a hold that contains at least one active content
|
||||
* When I use the existing REST API to retrieve the holds the content is added
|
||||
* Then the hold where the content held is returned
|
||||
*/
|
||||
@Test
|
||||
public void retrieveTheHoldWhereTheContentIsAdded()
|
||||
{
|
||||
RestNodeAssociationModelCollection holdsEntries = getRestAPIFactory()
|
||||
.getNodeAPI(documentHeld).usingParams("where=(assocType='rma:frozenContent')").getParents();
|
||||
Hold retrievedHold = getRestAPIFactory().getHoldsAPI(getAdminUser())
|
||||
.getHold(holdsEntries.getEntries().get(0).getModel().getId());
|
||||
assertEquals(retrievedHold, hold, "Holds are not equal");
|
||||
}
|
||||
|
||||
/**
|
||||
* Valid nodes to be added to hold
|
||||
*/
|
||||
@DataProvider(name = "validNodesForAddToHold")
|
||||
public Object[][] getValidNodesForAddToHold()
|
||||
{
|
||||
//create electronic and nonElectronic record in record folder
|
||||
RecordCategoryChild recordFolder = createCategoryFolderInFilePlan();
|
||||
RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
|
||||
nodesToBeClean.add(recordFolder.getParentId());
|
||||
Record electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolder.getId(),
|
||||
getFile
|
||||
(IMAGE_FILE));
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
Record nonElectronicRecord = recordFolderAPI.createRecord(createNonElectronicRecordModel(),
|
||||
recordFolder.getId());
|
||||
assertStatusCode(CREATED);
|
||||
getRestAPIFactory().getRMUserAPI().addUserPermission(recordFolder.getId(), userAddHoldPermission,
|
||||
PERMISSION_FILING);
|
||||
|
||||
RecordCategoryChild folderToHold = createCategoryFolderInFilePlan();
|
||||
getRestAPIFactory().getRMUserAPI().addUserPermission(folderToHold.getId(), userAddHoldPermission,
|
||||
PERMISSION_FILING);
|
||||
nodesToBeClean.add(folderToHold.getParentId());
|
||||
|
||||
return new String[][]
|
||||
{ // record folder
|
||||
{ folderToHold.getId() },
|
||||
//electronic record
|
||||
{ electronicRecord.getId() },
|
||||
// non electronic record
|
||||
{ nonElectronicRecord.getId() },
|
||||
// document from collaboration site
|
||||
{ contentToAddToHold.getNodeRefWithoutVersion() },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given record folder/record/document not on hold
|
||||
* And a hold
|
||||
* And file permission on the hold
|
||||
* And the appropriate capability to add to hold
|
||||
* When I use the existing REST API to add the node to the hold
|
||||
* Then the record folder/record/document is added to the hold
|
||||
* And the item is frozen
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test(dataProvider = "validNodesForAddToHold")
|
||||
public void addValidNodesToHoldWithAllowedUser(String nodeId) throws Exception
|
||||
{
|
||||
STEP("Add node to hold with user with permission.");
|
||||
getRestAPIFactory().getHoldsAPI(userAddHoldPermission)
|
||||
.addChildToHold(HoldChild.builder().id(nodeId).build(), hold.getId());
|
||||
|
||||
STEP("Check the node is frozen.");
|
||||
assertTrue(hasAspect(nodeId, FROZEN_ASPECT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with user without correct permission to add to hold and the node ref to be added to hold
|
||||
*
|
||||
* @return object with user model and the node ref to be added to hold
|
||||
*/
|
||||
@DataProvider(name = "userWithoutPermissionForAddToHold")
|
||||
public Object[][] getUserWithoutPermissionForAddToHold()
|
||||
{
|
||||
//create record folder
|
||||
RecordCategoryChild recordFolder = createCategoryFolderInFilePlan();
|
||||
//create a rm manager and grant read permission over the record folder created
|
||||
UserModel user = roleService.createUserWithRMRoleAndRMNodePermission(ROLE_RM_MANAGER.roleId,
|
||||
recordFolder.getId(),
|
||||
PERMISSION_READ_RECORDS);
|
||||
getRestAPIFactory().getRMUserAPI().addUserPermission(holdNodeRef, user, PERMISSION_FILING);
|
||||
nodesToBeClean.add(recordFolder.getParentId());
|
||||
return new Object[][]
|
||||
{ // user without write permission on the content
|
||||
{
|
||||
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole.SiteConsumer,
|
||||
holdNodeRef, UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING),
|
||||
contentAddToHoldNoPermission.getNodeRefWithoutVersion()
|
||||
},
|
||||
// user with write permission on the content and without filling permission on a hold
|
||||
{
|
||||
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole
|
||||
.SiteCollaborator,
|
||||
holdNodeRef, UserRoles.ROLE_RM_MANAGER, PERMISSION_READ_RECORDS),
|
||||
contentAddToHoldNoPermission.getNodeRefWithoutVersion()
|
||||
},
|
||||
// user with write permission on the content, filling permission on a hold without add to
|
||||
// hold capability
|
||||
{
|
||||
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole
|
||||
.SiteCollaborator,
|
||||
holdNodeRef, UserRoles.ROLE_RM_POWER_USER, PERMISSION_READ_RECORDS),
|
||||
contentAddToHoldNoPermission.getNodeRefWithoutVersion()
|
||||
},
|
||||
//user without write permission on RM record folder
|
||||
{
|
||||
user, recordFolder.getId()
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a node not on hold
|
||||
* And a hold
|
||||
* And user without right permission to add to hold
|
||||
* When I use the existing REST API to add the node to the hold
|
||||
* Then the node is not added to the hold
|
||||
* And the node is not frozen
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test(dataProvider = "userWithoutPermissionForAddToHold")
|
||||
public void addContentToHoldWithUserWithoutHoldPermission(UserModel userModel, String nodeToBeAddedToHold)
|
||||
throws Exception
|
||||
{
|
||||
users.add(userModel);
|
||||
STEP("Add the node to the hold with user without permission.");
|
||||
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(userModel)
|
||||
.addChildToHold(HoldChild.builder().id(nodeToBeAddedToHold).build(), holdNodeRef);
|
||||
|
||||
assertStatusCode(FORBIDDEN);
|
||||
getRestAPIFactory().getRmRestWrapper().assertLastError().containsSummary(ACCESS_DENIED_ERROR_MESSAGE);
|
||||
|
||||
STEP("Check the node is not frozen.");
|
||||
assertFalse(hasAspect(nodeToBeAddedToHold, FROZEN_ASPECT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with invalid node types that can be added to a hold
|
||||
*/
|
||||
@DataProvider(name = "invalidNodesForAddToHold")
|
||||
public Object[][] getInvalidNodesForAddToHold()
|
||||
{
|
||||
//create locked file
|
||||
FileModel contentLocked = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
contentActions.checkOut(getAdminUser().getUsername(), getAdminUser().getPassword(),
|
||||
testSite.getId(), contentLocked.getName());
|
||||
RecordCategory category = createRootCategory(getRandomAlphanumeric());
|
||||
nodesToBeClean.add(category.getId());
|
||||
return new Object[][]
|
||||
{ // file plan node id
|
||||
{ getFilePlan(FILE_PLAN_ALIAS).getId(), SC_BAD_REQUEST, INVALID_TYPE_ERROR_MESSAGE },
|
||||
//transfer container
|
||||
{ getTransferContainer(TRANSFERS_ALIAS).getId(), SC_BAD_REQUEST, INVALID_TYPE_ERROR_MESSAGE },
|
||||
// a record category
|
||||
{ category.getId(), SC_BAD_REQUEST, INVALID_TYPE_ERROR_MESSAGE },
|
||||
// unfiled records root
|
||||
{ getUnfiledContainer(UNFILED_RECORDS_CONTAINER_ALIAS).getId(), SC_BAD_REQUEST,
|
||||
INVALID_TYPE_ERROR_MESSAGE },
|
||||
// an arbitrary unfiled records folder
|
||||
{ createUnfiledContainerChild(UNFILED_RECORDS_CONTAINER_ALIAS, "Unfiled Folder " +
|
||||
getRandomAlphanumeric(), UNFILED_RECORD_FOLDER_TYPE).getId(), SC_BAD_REQUEST,
|
||||
INVALID_TYPE_ERROR_MESSAGE },
|
||||
//folder,
|
||||
{ dataContent.usingAdmin().usingSite(testSite).createFolder().getNodeRef(), SC_BAD_REQUEST,
|
||||
INVALID_TYPE_ERROR_MESSAGE },
|
||||
//document locked
|
||||
{ contentLocked.getNodeRefWithoutVersion(), SC_BAD_REQUEST, LOCKED_FILE_ERROR_MESSAGE }
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a node that is not a document/record/ record folder ( a valid node type to be added to hold)
|
||||
* And a hold
|
||||
* And user without right permission to add to hold
|
||||
* When I use the existing REST API to add the node to the hold
|
||||
* Then the node is not added to the hold
|
||||
* And the node is not frozen
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test(dataProvider = "invalidNodesForAddToHold")
|
||||
public void addInvalidNodesToHold(String itemNodeRef, int responseCode, String errorMessage) throws Exception
|
||||
{
|
||||
STEP("Add the node to the hold ");
|
||||
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(itemNodeRef).build(), holdNodeRef);
|
||||
|
||||
assertStatusCode(HttpStatus.valueOf(responseCode));
|
||||
getRestAPIFactory().getRmRestWrapper().assertLastError().containsSummary(errorMessage);
|
||||
|
||||
STEP("Check node is not frozen.");
|
||||
assertFalse(hasAspect(itemNodeRef, FROZEN_ASPECT));
|
||||
}
|
||||
|
||||
private Hold createHold(String parentId, Hold hold, UserModel user)
|
||||
{
|
||||
FilePlanAPI filePlanAPI = getRestAPIFactory().getFilePlansAPI(user);
|
||||
return filePlanAPI.createHold(hold, parentId);
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void cleanUpAddContentToHold()
|
||||
{
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser()).deleteHold(holdNodeRef);
|
||||
dataSite.usingAdmin().deleteSite(testSite);
|
||||
users.forEach(user -> getDataUser().usingAdmin().deleteUser(user));
|
||||
nodesToBeClean.forEach(this::deleteRecordCategory);
|
||||
}
|
||||
}
|
@@ -0,0 +1,186 @@
|
||||
/*-
|
||||
* #%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.model.fileplancomponents.FilePlanComponentAlias.FILE_PLAN_ALIAS;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomAlphanumeric;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
|
||||
import static org.springframework.http.HttpStatus.NO_CONTENT;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldDeletionReason;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* This class contains the tests for the Holds CRUD V1 API
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
public class HoldsTests extends BaseRMRestTest
|
||||
{
|
||||
|
||||
private final List<String> nodeRefs = new ArrayList<>();
|
||||
|
||||
@Test
|
||||
public void testGetHold()
|
||||
{
|
||||
String holdName = "Hold" + getRandomAlphanumeric();
|
||||
String holdDescription = "Description" + getRandomAlphanumeric();
|
||||
String holdReason = "Reason" + getRandomAlphanumeric();
|
||||
|
||||
// Create the hold
|
||||
Hold hold = Hold.builder()
|
||||
.name(holdName)
|
||||
.description(holdDescription)
|
||||
.reason(holdReason)
|
||||
.build();
|
||||
Hold createdHold = getRestAPIFactory().getFilePlansAPI()
|
||||
.createHold(hold, FILE_PLAN_ALIAS);
|
||||
|
||||
// Get the hold
|
||||
Hold receivedHold = getRestAPIFactory().getHoldsAPI().getHold(createdHold.getId());
|
||||
nodeRefs.add(receivedHold.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(OK);
|
||||
|
||||
assertEquals(receivedHold.getName(), holdName);
|
||||
assertEquals(receivedHold.getDescription(), holdDescription);
|
||||
assertEquals(receivedHold.getReason(), holdReason);
|
||||
assertNotNull(receivedHold.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateHold()
|
||||
{
|
||||
String holdName = "Hold" + getRandomAlphanumeric();
|
||||
String holdDescription = "Description" + getRandomAlphanumeric();
|
||||
String holdReason = "Reason" + getRandomAlphanumeric();
|
||||
|
||||
// Create the hold
|
||||
Hold hold = Hold.builder()
|
||||
.name(holdName)
|
||||
.description(holdDescription)
|
||||
.reason(holdReason)
|
||||
.build();
|
||||
Hold createdHold = getRestAPIFactory().getFilePlansAPI()
|
||||
.createHold(hold, FILE_PLAN_ALIAS);
|
||||
nodeRefs.add(createdHold.getId());
|
||||
|
||||
Hold holdModel = Hold.builder()
|
||||
.name("Updated" + holdName)
|
||||
.description("Updated" + holdDescription)
|
||||
.reason("Updated" + holdReason)
|
||||
.build();
|
||||
|
||||
// Update the hold
|
||||
Hold updatedHold = getRestAPIFactory().getHoldsAPI().updateHold(holdModel, createdHold.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(OK);
|
||||
|
||||
assertEquals(updatedHold.getName(), "Updated" + holdName);
|
||||
assertEquals(updatedHold.getDescription(), "Updated" + holdDescription);
|
||||
assertEquals(updatedHold.getReason(), "Updated" + holdReason);
|
||||
assertNotNull(updatedHold.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteHold()
|
||||
{
|
||||
String holdName = "Hold" + getRandomAlphanumeric();
|
||||
String holdDescription = "Description" + getRandomAlphanumeric();
|
||||
String holdReason = "Reason" + getRandomAlphanumeric();
|
||||
|
||||
// Create the hold
|
||||
Hold hold = Hold.builder()
|
||||
.name(holdName)
|
||||
.description(holdDescription)
|
||||
.reason(holdReason)
|
||||
.build();
|
||||
Hold createdHold = getRestAPIFactory().getFilePlansAPI()
|
||||
.createHold(hold, FILE_PLAN_ALIAS);
|
||||
nodeRefs.add(createdHold.getId());
|
||||
|
||||
// Delete the hold
|
||||
getRestAPIFactory().getHoldsAPI().deleteHold(createdHold.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(NO_CONTENT);
|
||||
|
||||
// Try to get the hold
|
||||
getRestAPIFactory().getHoldsAPI().getHold(createdHold.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteHoldWithReason()
|
||||
{
|
||||
String holdName = "Hold" + getRandomAlphanumeric();
|
||||
String holdDescription = "Description" + getRandomAlphanumeric();
|
||||
String holdReason = "Reason" + getRandomAlphanumeric();
|
||||
|
||||
// Create the hold
|
||||
Hold hold = Hold.builder()
|
||||
.name(holdName)
|
||||
.description(holdDescription)
|
||||
.reason(holdReason)
|
||||
.build();
|
||||
Hold createdHold = getRestAPIFactory().getFilePlansAPI()
|
||||
.createHold(hold, FILE_PLAN_ALIAS);
|
||||
nodeRefs.add(createdHold.getId());
|
||||
|
||||
// Delete the hold with the reason
|
||||
getRestAPIFactory().getHoldsAPI()
|
||||
.deleteHoldWithReason(HoldDeletionReason.builder().reason("Example reason").build(), createdHold.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(OK);
|
||||
|
||||
// Try to get the hold
|
||||
getRestAPIFactory().getHoldsAPI().getHold(createdHold.getId());
|
||||
|
||||
// Verify the status code
|
||||
assertStatusCode(NOT_FOUND);
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void cleanUpHoldsTests()
|
||||
{
|
||||
nodeRefs.forEach(nodeRef -> getRestAPIFactory().getHoldsAPI(getAdminUser()).deleteHold(nodeRef));
|
||||
}
|
||||
}
|
@@ -0,0 +1,337 @@
|
||||
/*-
|
||||
* #%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.fileplancomponents.FilePlanComponentAspects.ASPECTS_VITAL_RECORD;
|
||||
import static org.alfresco.rest.rm.community.model.fileplancomponents.FilePlanComponentAspects.ASPECTS_VITAL_RECORD_DEFINITION;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.rest.rm.community.utils.CoreUtil.createBodyForMoveCopy;
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.apache.commons.httpclient.HttpStatus.SC_INTERNAL_SERVER_ERROR;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.AssertJUnit.assertFalse;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonObject;
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.core.JsonBodyGenerator;
|
||||
import org.alfresco.rest.core.v0.BaseAPI.RM_ACTIONS;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.common.ReviewPeriod;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChild;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategory;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.rm.community.model.recordfolder.RecordFolder;
|
||||
import org.alfresco.rest.rm.community.model.recordfolder.RecordFolderProperties;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.FilePlanAPI;
|
||||
import org.alfresco.rest.v0.RMRolesAndActionsAPI;
|
||||
import org.alfresco.rest.v0.service.DispositionScheduleService;
|
||||
import org.alfresco.utility.Utility;
|
||||
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;
|
||||
|
||||
/**
|
||||
* V1 API tests to check actions on frozen content
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
public class PreventActionsOnFrozenContentV1Tests extends BaseRMRestTest
|
||||
{
|
||||
private static String holdNodeRef;
|
||||
private static FileModel contentHeld;
|
||||
private static File updatedFile;
|
||||
private static FolderModel folderModel;
|
||||
private static RecordCategoryChild recordFolder;
|
||||
private static Record recordFrozen;
|
||||
private static Record recordNotHeld;
|
||||
private static RecordCategory categoryWithRS;
|
||||
|
||||
private Hold hold;
|
||||
|
||||
@Autowired
|
||||
private DispositionScheduleService dispositionScheduleService;
|
||||
|
||||
@Autowired
|
||||
private RMRolesAndActionsAPI rmRolesAndActionsAPI;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void preconditionForPreventActionsOnFrozenContent()
|
||||
{
|
||||
String holdOne = "HOLD" + generateTestPrefix(PreventActionsOnFrozenContentV1Tests.class);
|
||||
|
||||
STEP("Create a hold.");
|
||||
hold = createHold(FILE_PLAN_ALIAS,
|
||||
Hold.builder().name(holdOne).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(), getAdminUser());
|
||||
holdNodeRef = hold.getId();
|
||||
|
||||
STEP("Create a test file.");
|
||||
testSite = dataSite.usingAdmin().createPublicRandomSite();
|
||||
contentHeld = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
STEP("Add the file to the hold.");
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(contentHeld.getNodeRefWithoutVersion()).build(), hold.getId());
|
||||
|
||||
STEP("Get a file resource.");
|
||||
updatedFile = Utility.getResourceTestDataFile("SampleTextFile_10kb.txt");
|
||||
|
||||
STEP("Create a folder withing the test site .");
|
||||
folderModel = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createFolder();
|
||||
|
||||
STEP("Create a record folder with some records");
|
||||
recordFolder = createCategoryFolderInFilePlan();
|
||||
recordFrozen = createElectronicRecord(recordFolder.getId(), getRandomName("elRecordFrozen"));
|
||||
recordNotHeld = createElectronicRecord(recordFolder.getId(), getRandomName("elRecordNotHeld"));
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
STEP("Add the record to the hold.");
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(recordFrozen.getId()).build(), hold.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Given active content on hold
|
||||
* When I try to edit the properties
|
||||
* Or perform an action that edits the properties
|
||||
* Then I am not successful
|
||||
*/
|
||||
@Test
|
||||
public void editPropertiesForContentHeld() throws Exception
|
||||
{
|
||||
STEP("Update name property of the held content");
|
||||
JsonObject nameUpdated = Json.createObjectBuilder().add("name", "HeldNameUpdated").build();
|
||||
restClient.authenticateUser(getAdminUser()).withCoreAPI().usingNode(contentHeld)
|
||||
.updateNode(nameUpdated.toString());
|
||||
|
||||
STEP("Check the request failed.");
|
||||
restClient.assertStatusCodeIs(FORBIDDEN);
|
||||
restClient.assertLastError().containsSummary("Frozen content can't be updated.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Given active content on hold
|
||||
* When I try to update the content
|
||||
* Then I am not successful
|
||||
*/
|
||||
@Test
|
||||
public void updateContentForFrozenFile() throws Exception
|
||||
{
|
||||
STEP("Update content of the held file");
|
||||
restClient.authenticateUser(getAdminUser()).withCoreAPI().usingNode(contentHeld).updateNodeContent(updatedFile);
|
||||
|
||||
STEP("Check the request failed.");
|
||||
restClient.assertStatusCodeIs(INTERNAL_SERVER_ERROR);
|
||||
restClient.assertLastError().containsSummary("Frozen content can't be updated.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Given active content on hold
|
||||
* When I try to delete the content
|
||||
* Then I am not successful
|
||||
*/
|
||||
@Test
|
||||
public void deleteFrozenFile() throws Exception
|
||||
{
|
||||
STEP("Delete frozen file");
|
||||
restClient.authenticateUser(getAdminUser()).withCoreAPI().usingNode(contentHeld)
|
||||
.deleteNode(contentHeld.getNodeRefWithoutVersion());
|
||||
|
||||
STEP("Check the request failed.");
|
||||
restClient.assertStatusCodeIs(FORBIDDEN);
|
||||
restClient.assertLastError().containsSummary("Frozen content can't be deleted.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Given active content on hold
|
||||
* When I try to copy the content
|
||||
* Then I am not successful
|
||||
*/
|
||||
@Test
|
||||
public void copyFrozenFile()
|
||||
{
|
||||
STEP("Copy frozen file");
|
||||
String postBody = JsonBodyGenerator.keyValueJson("targetParentId", folderModel.getNodeRef());
|
||||
getRestAPIFactory().getNodeAPI(contentHeld).copyNode(postBody);
|
||||
|
||||
STEP("Check the request failed.");
|
||||
assertStatusCode(FORBIDDEN);
|
||||
getRestAPIFactory().getRmRestWrapper().assertLastError().containsSummary("Permission was denied");
|
||||
}
|
||||
|
||||
/**
|
||||
* Given active content on hold
|
||||
* When I try to move the content
|
||||
* Then I am not successful
|
||||
*/
|
||||
@Test
|
||||
public void moveFrozenFile() throws Exception
|
||||
{
|
||||
STEP("Move frozen file");
|
||||
getRestAPIFactory().getNodeAPI(contentHeld).move(createBodyForMoveCopy(folderModel.getNodeRef()));
|
||||
|
||||
STEP("Check the request failed.");
|
||||
assertStatusCode(FORBIDDEN);
|
||||
getRestAPIFactory().getRmRestWrapper().assertLastError().containsSummary("Frozen content can't be moved.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a record folder with a frozen record and another record not held
|
||||
* When I update the record folder and make the records as vital
|
||||
* Then I am successful and the records not held are marked as vital
|
||||
* And the frozen nodes have the vital record search properties updated
|
||||
*/
|
||||
@Test
|
||||
public void updateRecordFolderVitalProperties()
|
||||
{
|
||||
STEP("Update the vital record properties for the record folder");
|
||||
// Create the record folder properties to update
|
||||
RecordFolder recordFolderToUpdate = RecordFolder.builder()
|
||||
.properties(RecordFolderProperties.builder()
|
||||
.vitalRecordIndicator(true)
|
||||
.reviewPeriod(new ReviewPeriod("month", "1"))
|
||||
.build())
|
||||
.build();
|
||||
|
||||
// Update the record folder
|
||||
RecordFolder updatedRecordFolder = getRestAPIFactory().getRecordFolderAPI().updateRecordFolder
|
||||
(recordFolderToUpdate,
|
||||
recordFolder.getId());
|
||||
assertStatusCode(OK);
|
||||
assertTrue(updatedRecordFolder.getAspectNames().contains(ASPECTS_VITAL_RECORD_DEFINITION));
|
||||
|
||||
STEP("Check the frozen record was not marked as vital");
|
||||
recordFrozen = getRestAPIFactory().getRecordsAPI().getRecord(recordFrozen.getId());
|
||||
assertFalse(recordFrozen.getAspectNames().contains(ASPECTS_VITAL_RECORD));
|
||||
assertTrue(recordFrozen.getProperties().getRecordSearchVitalRecordReviewPeriod().contains("month"));
|
||||
assertTrue(recordFrozen.getProperties().getRecordSearchVitalRecordReviewPeriodExpression().contains("1"));
|
||||
|
||||
STEP("Check the record not held was marked as vital");
|
||||
recordNotHeld = getRestAPIFactory().getRecordsAPI().getRecord(recordNotHeld.getId());
|
||||
assertTrue(recordNotHeld.getAspectNames().contains(ASPECTS_VITAL_RECORD));
|
||||
assertNotNull(recordNotHeld.getProperties().getReviewAsOf());
|
||||
assertTrue(recordNotHeld.getProperties().getRecordSearchVitalRecordReviewPeriod().contains("month"));
|
||||
assertTrue(recordNotHeld.getProperties().getRecordSearchVitalRecordReviewPeriodExpression().contains("1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a record folder with a frozen record and another record not held
|
||||
* When I add a disposition schedule
|
||||
* Then I am successful
|
||||
* And the record search disposition schedule properties are updated
|
||||
*/
|
||||
@Test
|
||||
public void createDispositionScheduleOnCategoryWithHeldChildren()
|
||||
{
|
||||
STEP("Create a retention schedule on the category with frozen children");
|
||||
RecordCategory categoryWithRS = getRestAPIFactory().getRecordCategoryAPI()
|
||||
.getRecordCategory(recordFolder.getParentId());
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(categoryWithRS.getName(), false);
|
||||
dispositionScheduleService.addCutOffImmediatelyStep(categoryWithRS.getName());
|
||||
dispositionScheduleService.addDestroyWithGhostingImmediatelyAfterCutOff(categoryWithRS.getName());
|
||||
|
||||
STEP("Check the record folder has a disposition schedule");
|
||||
RecordFolder folderWithRS = getRestAPIFactory().getRecordFolderAPI().getRecordFolder(recordFolder.getId());
|
||||
assertNotNull(folderWithRS.getProperties().getRecordSearchDispositionAuthority());
|
||||
assertNotNull(folderWithRS.getProperties().getRecordSearchDispositionInstructions());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a record category with a disposition schedule applied to records
|
||||
* And the disposition schedule has a retain step immediately and destroy step immediately
|
||||
* And a complete record added to one hold
|
||||
* When I execute the retain action
|
||||
* Then the action is executed
|
||||
* And the record search disposition schedule properties are updated
|
||||
*/
|
||||
@Test
|
||||
public void retainActionOnFrozenHeldRecords()
|
||||
{
|
||||
STEP("Add a category with a disposition schedule.");
|
||||
categoryWithRS = createRootCategory(getRandomName("CategoryWithRS"));
|
||||
dispositionScheduleService.createCategoryRetentionSchedule(categoryWithRS.getName(), true);
|
||||
dispositionScheduleService.addRetainAfterPeriodStep(categoryWithRS.getName(), "immediately");
|
||||
dispositionScheduleService.addDestroyWithGhostingImmediatelyAfterCutOff(categoryWithRS.getName());
|
||||
|
||||
STEP("Create record folder with a record.");
|
||||
RecordCategoryChild folder = createFolder(categoryWithRS.getId(), getRandomName("RecFolder"));
|
||||
Record record = createElectronicRecord(folder.getId(), getRandomName("elRecord"));
|
||||
completeRecord(record.getId());
|
||||
|
||||
STEP("Add the record to the hold");
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(record.getId()).build(), hold.getId());
|
||||
|
||||
STEP("Execute the retain action");
|
||||
rmRolesAndActionsAPI.executeAction(getAdminUser().getUsername(), getAdminUser().getPassword(), record.getName(),
|
||||
RM_ACTIONS.END_RETENTION, null, SC_INTERNAL_SERVER_ERROR);
|
||||
|
||||
STEP("Check the record search disposition properties");
|
||||
Record recordUpdated = getRestAPIFactory().getRecordsAPI().getRecord(record.getId());
|
||||
assertTrue(recordUpdated.getProperties().getRecordSearchDispositionActionName()
|
||||
.contains(RM_ACTIONS.END_RETENTION.getAction()));
|
||||
assertTrue(recordUpdated.getProperties().getRecordSearchDispositionPeriod().contains("immediately"));
|
||||
}
|
||||
|
||||
private Hold createHold(String parentId, Hold hold, UserModel user)
|
||||
{
|
||||
FilePlanAPI filePlanAPI = getRestAPIFactory().getFilePlansAPI(user);
|
||||
return filePlanAPI.createHold(hold, parentId);
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void cleanUpPreventActionsOnFrozenContent()
|
||||
{
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser()).deleteHold(holdNodeRef);
|
||||
dataSite.usingAdmin().deleteSite(testSite);
|
||||
deleteRecordCategory(recordFolder.getParentId());
|
||||
deleteRecordCategory(categoryWithRS.getId());
|
||||
}
|
||||
}
|
@@ -52,7 +52,7 @@ import java.util.Set;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldEntry;
|
||||
import org.alfresco.rest.rm.community.model.hold.v0.HoldEntry;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
|
@@ -0,0 +1,374 @@
|
||||
/*-
|
||||
* #%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 java.util.Arrays.asList;
|
||||
|
||||
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.fileplancomponents.FilePlanComponentAspects.FROZEN_ASPECT;
|
||||
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.model.user.UserRoles.ROLE_RM_MANAGER;
|
||||
import static org.alfresco.rest.rm.community.util.CommonTestUtils.generateTestPrefix;
|
||||
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.IMAGE_FILE;
|
||||
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createElectronicRecordModel;
|
||||
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.createNonElectronicRecordModel;
|
||||
import static org.alfresco.rest.rm.community.utils.FilePlanComponentsUtil.getFile;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.CREATED;
|
||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.alfresco.dataprep.CMISUtil;
|
||||
import org.alfresco.rest.model.RestNodeAssociationModelCollection;
|
||||
import org.alfresco.rest.rm.community.base.BaseRMRestTest;
|
||||
import org.alfresco.rest.rm.community.model.hold.Hold;
|
||||
import org.alfresco.rest.rm.community.model.hold.HoldChild;
|
||||
import org.alfresco.rest.rm.community.model.record.Record;
|
||||
import org.alfresco.rest.rm.community.model.recordcategory.RecordCategoryChild;
|
||||
import org.alfresco.rest.rm.community.model.user.UserRoles;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.FilePlanAPI;
|
||||
import org.alfresco.rest.rm.community.requests.gscore.api.RecordFolderAPI;
|
||||
import org.alfresco.rest.rm.community.utils.CoreUtil;
|
||||
import org.alfresco.rest.v0.service.RoleService;
|
||||
import org.alfresco.utility.constants.UserRole;
|
||||
import org.alfresco.utility.model.FileModel;
|
||||
import org.alfresco.utility.model.SiteModel;
|
||||
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.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* V1 API tests for removing content/record folder/record from holds
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
public class RemoveFromHoldsV1Tests extends BaseRMRestTest
|
||||
{
|
||||
private static final String HOLD_ONE = "HOLD_ONE" + generateTestPrefix(RemoveFromHoldsV1Tests.class);
|
||||
private static final String HOLD_TWO = "HOLD_TWO" + generateTestPrefix(RemoveFromHoldsV1Tests.class);
|
||||
private static final String ACCESS_DENIED_ERROR_MESSAGE = "Access Denied. You do not have the appropriate " +
|
||||
"permissions to perform this operation.";
|
||||
|
||||
private SiteModel testSite;
|
||||
private SiteModel privateSite;
|
||||
private String holdNodeRefOne;
|
||||
private FileModel contentHeld;
|
||||
private FileModel contentAddToManyHolds;
|
||||
private List<String> holdsListRef = new ArrayList<>();
|
||||
private final Set<UserModel> usersToBeClean = new HashSet<>();
|
||||
private final Set<String> nodesToBeClean = new HashSet<>();
|
||||
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
@BeforeClass(alwaysRun = true)
|
||||
public void preconditionForRemoveContentFromHold()
|
||||
{
|
||||
STEP("Create two holds.");
|
||||
|
||||
holdNodeRefOne = createHold(FILE_PLAN_ALIAS,
|
||||
Hold.builder().name(HOLD_ONE).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(),
|
||||
getAdminUser()).getId();
|
||||
String holdNodeRefTwo = createHold(FILE_PLAN_ALIAS,
|
||||
Hold.builder().name(HOLD_TWO).description(HOLD_DESCRIPTION).reason(HOLD_REASON).build(),
|
||||
getAdminUser()).getId();
|
||||
holdsListRef = asList(holdNodeRefOne, holdNodeRefTwo);
|
||||
|
||||
STEP("Create test files.");
|
||||
testSite = dataSite.usingAdmin().createPublicRandomSite();
|
||||
privateSite = dataSite.usingAdmin().createPrivateRandomSite();
|
||||
contentHeld = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
contentAddToManyHolds = dataContent.usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
STEP("Add content to the holds.");
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(contentHeld.getNodeRefWithoutVersion()).build(), holdNodeRefOne);
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(contentAddToManyHolds.getNodeRefWithoutVersion()).build(),
|
||||
holdNodeRefOne);
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(contentAddToManyHolds.getNodeRefWithoutVersion()).build(),
|
||||
holdNodeRefTwo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Valid nodes to be removed from hold
|
||||
*/
|
||||
@DataProvider(name = "validNodesToRemoveFromHold")
|
||||
public Object[][] getValidNodesToRemoveFromHold()
|
||||
{
|
||||
//create electronic and nonElectronic record in record folder
|
||||
RecordCategoryChild recordFolder = createCategoryFolderInFilePlan();
|
||||
RecordFolderAPI recordFolderAPI = getRestAPIFactory().getRecordFolderAPI();
|
||||
nodesToBeClean.add(recordFolder.getParentId());
|
||||
Record electronicRecord = recordFolderAPI.createRecord(createElectronicRecordModel(), recordFolder.getId(),
|
||||
getFile
|
||||
(IMAGE_FILE));
|
||||
assertStatusCode(CREATED);
|
||||
Record nonElectronicRecord = recordFolderAPI.createRecord(createNonElectronicRecordModel(),
|
||||
recordFolder.getId());
|
||||
assertStatusCode(CREATED);
|
||||
|
||||
RecordCategoryChild folderToHeld = createCategoryFolderInFilePlan();
|
||||
nodesToBeClean.add(folderToHeld.getParentId());
|
||||
Stream.of(electronicRecord.getId(), nonElectronicRecord.getId(), folderToHeld.getId())
|
||||
.forEach(id -> getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(id).build(), holdNodeRefOne));
|
||||
|
||||
return new String[][]
|
||||
{ // record folder
|
||||
{ folderToHeld.getId() },
|
||||
//electronic record
|
||||
{ electronicRecord.getId() },
|
||||
// non electronic record
|
||||
{ nonElectronicRecord.getId() },
|
||||
// document from collaboration site
|
||||
{ contentHeld.getNodeRefWithoutVersion() },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given content/record folder/record that is held
|
||||
* And the corresponding hold
|
||||
* When I use the existing REST API to remove the node from the hold
|
||||
* Then the node is removed from the hold
|
||||
* And is no longer frozen
|
||||
*/
|
||||
@Test(dataProvider = "validNodesToRemoveFromHold")
|
||||
public void removeContentFromHold(String nodeId) throws Exception
|
||||
{
|
||||
STEP("Remove node from hold");
|
||||
getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser()).deleteHoldChild(holdNodeRefOne, nodeId);
|
||||
|
||||
STEP("Check the node is not held");
|
||||
assertFalse(hasAspect(nodeId, FROZEN_ASPECT));
|
||||
|
||||
STEP("Check node is not in any hold");
|
||||
RestNodeAssociationModelCollection holdsEntries = getRestAPIFactory()
|
||||
.getNodeAPI(CoreUtil.toContentModel(nodeId)).usingParams("where=(assocType='rma:frozenContent')")
|
||||
.getParents();
|
||||
assertTrue(holdsEntries.getEntries().isEmpty(), "Content held is still added to a hold.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Given active content that is held on many holds
|
||||
* When I use the existing REST API to remove the active content from one hold
|
||||
* Then the active content is removed from the specific hold
|
||||
* And is frozen
|
||||
* And in the other holds
|
||||
*/
|
||||
@Test
|
||||
public void removeContentAddedToManyHolds() throws Exception
|
||||
{
|
||||
STEP("Remove content from hold. ");
|
||||
|
||||
getRestAPIFactory().getHoldsAPI(getAdminUser())
|
||||
.deleteHoldChild(holdNodeRefOne, contentAddToManyHolds.getNodeRefWithoutVersion());
|
||||
|
||||
STEP("Check the content is held. ");
|
||||
assertTrue(hasAspect(contentAddToManyHolds.getNodeRefWithoutVersion(), FROZEN_ASPECT));
|
||||
|
||||
STEP("Check node is in hold HOLD_TWO. ");
|
||||
|
||||
RestNodeAssociationModelCollection holdsEntries = getRestAPIFactory()
|
||||
.getNodeAPI(CoreUtil.toContentModel(contentAddToManyHolds.getNodeRefWithoutVersion()))
|
||||
.usingParams("where=(assocType='rma:frozenContent')").getParents();
|
||||
assertFalse(holdsEntries.getEntries().isEmpty(), "Content held is not held after removing from one hold.");
|
||||
assertTrue(holdsEntries.getEntries().stream()
|
||||
.anyMatch(restNodeModel -> restNodeModel.getModel().getName().equals(HOLD_TWO)),
|
||||
"Content held is not held after removing from one hold.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with user without right permission or capability to remove from hold a specific node
|
||||
*
|
||||
* @return user model and the node ref to be removed from hold
|
||||
*/
|
||||
@DataProvider(name = "userWithoutPermissionForRemoveFromHold")
|
||||
public Object[][] getUserWithoutPermissionForAddToHold()
|
||||
{
|
||||
//create record folder
|
||||
RecordCategoryChild recordFolder = createCategoryFolderInFilePlan();
|
||||
nodesToBeClean.add(recordFolder.getParentId());
|
||||
UserModel user = roleService.createUserWithRMRole(ROLE_RM_MANAGER.roleId);
|
||||
getRestAPIFactory().getRMUserAPI().addUserPermission(holdNodeRefOne, user, PERMISSION_FILING);
|
||||
//create files that will be removed from hold
|
||||
FileModel contentNoHoldPerm = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
FileModel contentNoHoldCap = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
FileModel privateFile = dataContent.usingAdmin().usingSite(privateSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
//add files to hold
|
||||
asList(recordFolder.getId(), contentNoHoldCap.getNodeRefWithoutVersion(),
|
||||
contentNoHoldPerm.getNodeRefWithoutVersion(), privateFile.getNodeRefWithoutVersion())
|
||||
.forEach(id -> getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(id).build(), holdNodeRefOne));
|
||||
|
||||
return new Object[][]
|
||||
{
|
||||
// user with read permission on the content, with remove from hold capability and without
|
||||
// filling permission on a hold
|
||||
{
|
||||
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole.SiteCollaborator,
|
||||
holdNodeRefOne, UserRoles.ROLE_RM_MANAGER, PERMISSION_READ_RECORDS),
|
||||
contentNoHoldPerm.getNodeRefWithoutVersion()
|
||||
},
|
||||
// user with write permission on the content, filling permission on a hold without remove from
|
||||
// hold capability
|
||||
{
|
||||
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole
|
||||
.SiteCollaborator,
|
||||
holdNodeRefOne, UserRoles.ROLE_RM_POWER_USER, PERMISSION_FILING),
|
||||
contentNoHoldCap.getNodeRefWithoutVersion()
|
||||
},
|
||||
//user without read permission on RM record folder
|
||||
{
|
||||
user, recordFolder.getId()
|
||||
},
|
||||
//user without read permission over the content from the private site
|
||||
{
|
||||
user, privateFile.getNodeRefWithoutVersion()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given node on hold in a single hold location
|
||||
* And the user does not have sufficient permissions or capabilities to remove the node from the hold
|
||||
* When the user tries to remove the node from the hold
|
||||
* Then it's unsuccessful
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test(dataProvider = "userWithoutPermissionForRemoveFromHold")
|
||||
public void removeFromHoldWithUserWithoutPermission(UserModel userModel, String nodeIdToBeRemoved) throws Exception
|
||||
{
|
||||
STEP("Update the list of users to be deleted after running the tests");
|
||||
usersToBeClean.add(userModel);
|
||||
|
||||
STEP("Remove node from hold with user without right permission or capability");
|
||||
getRestAPIFactory().getHoldsAPI(userModel).deleteHoldChild(holdNodeRefOne, nodeIdToBeRemoved);
|
||||
|
||||
assertStatusCode(FORBIDDEN);
|
||||
getRestAPIFactory().getRmRestWrapper().assertLastError().containsSummary(ACCESS_DENIED_ERROR_MESSAGE);
|
||||
|
||||
STEP("Check node is frozen.");
|
||||
assertTrue(hasAspect(nodeIdToBeRemoved, FROZEN_ASPECT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider with user with right permission or capability to remove from hold a specific node
|
||||
*
|
||||
* @return user model and the node ref to be removed from hold
|
||||
*/
|
||||
@DataProvider(name = "userWithPermissionForRemoveFromHold")
|
||||
public Object[][] getUserWithPermissionForAddToHold()
|
||||
{
|
||||
//create record folder
|
||||
RecordCategoryChild recordFolder = createCategoryFolderInFilePlan();
|
||||
nodesToBeClean.add(recordFolder.getParentId());
|
||||
UserModel user = roleService.createUserWithRMRoleAndRMNodePermission(ROLE_RM_MANAGER.roleId,
|
||||
recordFolder.getId(),
|
||||
PERMISSION_READ_RECORDS);
|
||||
getRestAPIFactory().getRMUserAPI().addUserPermission(holdNodeRefOne, user, PERMISSION_FILING);
|
||||
//create file that will be removed from hold
|
||||
FileModel contentPermission = dataContent.usingAdmin().usingSite(testSite)
|
||||
.createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
|
||||
//add files to hold
|
||||
asList(recordFolder.getId(), contentPermission.getNodeRefWithoutVersion())
|
||||
.forEach(id -> getRestAPIFactory()
|
||||
.getHoldsAPI(getAdminUser())
|
||||
.addChildToHold(HoldChild.builder().id(id).build(), holdNodeRefOne));
|
||||
|
||||
return new Object[][]
|
||||
{
|
||||
// user with write permission on the content
|
||||
{
|
||||
roleService.createUserWithSiteRoleRMRoleAndPermission(testSite, UserRole.SiteConsumer,
|
||||
holdNodeRefOne, UserRoles.ROLE_RM_MANAGER, PERMISSION_FILING),
|
||||
contentPermission.getNodeRefWithoutVersion()
|
||||
},
|
||||
//user with read permission on RM record folder
|
||||
{
|
||||
user, recordFolder.getId()
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "userWithPermissionForRemoveFromHold")
|
||||
public void removeFromHoldWithUserWithPermission(UserModel userModel, String nodeIdToBeRemoved) throws Exception
|
||||
{
|
||||
STEP("Update the list of users to be deleted after running the tests");
|
||||
usersToBeClean.add(userModel);
|
||||
|
||||
STEP("Remove node from hold with user with right permission and capability");
|
||||
getRestAPIFactory().getHoldsAPI(userModel).deleteHoldChild(holdNodeRefOne, nodeIdToBeRemoved);
|
||||
|
||||
STEP("Check node is not frozen.");
|
||||
assertFalse(hasAspect(nodeIdToBeRemoved, FROZEN_ASPECT));
|
||||
}
|
||||
|
||||
private Hold createHold(String parentId, Hold hold, UserModel user)
|
||||
{
|
||||
FilePlanAPI filePlanAPI = getRestAPIFactory().getFilePlansAPI(user);
|
||||
return filePlanAPI.createHold(hold, parentId);
|
||||
}
|
||||
|
||||
@AfterClass(alwaysRun = true)
|
||||
public void cleanUpRemoveContentFromHold()
|
||||
{
|
||||
holdsListRef.forEach(holdRef -> getRestAPIFactory().getHoldsAPI(getAdminUser()).deleteHold(holdRef));
|
||||
dataSite.usingAdmin().deleteSite(testSite);
|
||||
dataSite.usingAdmin().deleteSite(privateSite);
|
||||
usersToBeClean.forEach(user -> getDataUser().usingAdmin().deleteUser(user));
|
||||
nodesToBeClean.forEach(this::deleteRecordCategory);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
com.epam.reportportal.testng.ReportPortalTestNGListener
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>23.2.2.4-SNAPSHOT</version>
|
||||
<version>23.3.0.80</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -538,6 +538,11 @@
|
||||
<type>d:text</type>
|
||||
<mandatory>true</mandatory>
|
||||
</property>
|
||||
<property name="rma:holdDeletionReason">
|
||||
<title>Hold Deletion Reason</title>
|
||||
<type>d:text</type>
|
||||
<mandatory>false</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
|
||||
<associations>
|
||||
|
@@ -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">
|
||||
@@ -69,6 +70,39 @@
|
||||
<property name="transactionService" ref="transactionService" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rm.rest.api.fileplans.FilePlanHoldsRelation">
|
||||
<property name="apiUtils" ref="apiUtils" />
|
||||
<property name="nodesModelFactory" ref="nodesModelFactory" />
|
||||
<property name="holdService" ref="HoldService" />
|
||||
<property name="fileFolderService" ref="FileFolderService" />
|
||||
<property name="transactionService" ref="transactionService" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rm.rest.api.holds.HoldsEntityResource" >
|
||||
<property name="holdService" ref="HoldService" />
|
||||
<property name="apiUtils" ref="apiUtils" />
|
||||
<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">
|
||||
<property name="holdService" ref="HoldService" />
|
||||
<property name="apiUtils" ref="apiUtils" />
|
||||
<property name="nodesModelFactory" ref="nodesModelFactory" />
|
||||
<property name="fileFolderService" ref="FileFolderService" />
|
||||
<property name="transactionService" ref="transactionService" />
|
||||
<property name="permissionService" ref="PermissionService" />
|
||||
</bean>
|
||||
|
||||
<bean class="org.alfresco.rm.rest.api.unfiledcontainers.UnfiledContainerEntityResource">
|
||||
<property name="apiUtils" ref="apiUtils" />
|
||||
<property name="fileFolderService" ref="FileFolderService" />
|
||||
@@ -114,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" />
|
||||
|
@@ -1614,6 +1614,8 @@
|
||||
org.alfresco.module.org_alfresco_module_rm.hold.HoldService.createHold=RM_CAP.0.rma:filePlanComponent.CreateHold
|
||||
org.alfresco.module.org_alfresco_module_rm.hold.HoldService.getHoldReason=RM.Read.0
|
||||
org.alfresco.module.org_alfresco_module_rm.hold.HoldService.setHoldReason=RM_CAP.0.rma:filePlanComponent.EditHold
|
||||
org.alfresco.module.org_alfresco_module_rm.hold.HoldService.setHoldDeletionReason=RM_CAP.0.rma:filePlanComponent.EditHold
|
||||
org.alfresco.module.org_alfresco_module_rm.hold.HoldService.updateHold=RM_CAP.0.rma:filePlanComponent.EditHold
|
||||
org.alfresco.module.org_alfresco_module_rm.hold.HoldService.deleteHold=RM_CAP.0.rma:filePlanComponent.DeleteHold
|
||||
org.alfresco.module.org_alfresco_module_rm.hold.HoldService.addToHold=RM_CAP.0.rma:filePlanComponent.AddToHold
|
||||
org.alfresco.module.org_alfresco_module_rm.hold.HoldService.addToHolds=RM_ALLOW
|
||||
|
@@ -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.2.2.4-SNAPSHOT</version>
|
||||
<version>23.3.0.80</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
@@ -84,6 +84,11 @@
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.epam.reportportal</groupId>
|
||||
<artifactId>agent-java-testng</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
@@ -150,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>
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
package org.alfresco.module.org_alfresco_module_rm.audit.event;
|
||||
|
||||
import static org.alfresco.module.org_alfresco_module_rm.audit.event.HoldUtils.HOLD_DELETION_REASON;
|
||||
import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.EVERY_EVENT;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -77,6 +78,8 @@ public class DeleteHoldAuditEvent extends AuditEvent implements NodeServicePolic
|
||||
public void beforeDeleteNode(NodeRef holdNodeRef)
|
||||
{
|
||||
Map<QName, Serializable> auditProperties = HoldUtils.makePropertiesMap(holdNodeRef, nodeService);
|
||||
auditProperties.put(HOLD_DELETION_REASON, nodeService.getProperty(holdNodeRef, PROP_HOLD_DELETION_REASON));
|
||||
|
||||
recordsManagementAuditService.auditEvent(holdNodeRef, getName(), auditProperties, null, true, false);
|
||||
}
|
||||
}
|
||||
|
@@ -47,6 +47,7 @@ class HoldUtils
|
||||
{
|
||||
/** A QName to display for the hold name. */
|
||||
public static final QName HOLD_NAME = QName.createQName(RecordsManagementModel.RM_URI, "Hold Name");
|
||||
public static final QName HOLD_DELETION_REASON = QName.createQName(RecordsManagementModel.RM_URI, "Hold deletion reason");
|
||||
/** A QName to display for the hold node ref. */
|
||||
public static final QName HOLD_NODEREF = QName.createQName(RecordsManagementModel.RM_URI, "Hold NodeRef");
|
||||
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@@ -31,7 +31,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.declarative.DeclarativeCapability;
|
||||
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
|
||||
@@ -76,7 +75,7 @@ public class CreateCapability extends DeclarativeCapability
|
||||
@Override
|
||||
public int evaluate(NodeRef nodeRef)
|
||||
{
|
||||
return evaluate(nodeRef, null, null);
|
||||
return evaluate(nodeRef, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,9 +84,10 @@ public class CreateCapability extends DeclarativeCapability
|
||||
* @param destination destination node reference
|
||||
* @param linkee linkee node reference, can be null
|
||||
* @param assocType association type, can be null
|
||||
* @param recordType record type, can be null
|
||||
* @return
|
||||
*/
|
||||
public int evaluate(NodeRef destination, NodeRef linkee, QName assocType)
|
||||
public int evaluate(NodeRef destination, NodeRef linkee, QName assocType, QName recordType)
|
||||
{
|
||||
if (linkee != null)
|
||||
{
|
||||
@@ -105,7 +105,7 @@ public class CreateCapability extends DeclarativeCapability
|
||||
{
|
||||
if (recordService.isRecord(destination) &&
|
||||
!recordService.isDeclared(destination) &&
|
||||
permissionService.hasPermission(destination, RMPermissionModel.FILE_RECORDS) == AccessStatus.ALLOWED)
|
||||
permissionService.hasPermission(destination, FILE_RECORDS) == AccessStatus.ALLOWED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public class CreateCapability extends DeclarativeCapability
|
||||
if (recordService.isRecord(linkee) &&
|
||||
recordService.isRecord(destination) &&
|
||||
!recordService.isDeclared(destination) &&
|
||||
permissionService.hasPermission(destination, RMPermissionModel.FILE_RECORDS) == AccessStatus.ALLOWED)
|
||||
permissionService.hasPermission(destination, FILE_RECORDS) == AccessStatus.ALLOWED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
@@ -132,14 +132,15 @@ public class CreateCapability extends DeclarativeCapability
|
||||
|
||||
// if the destination folder is not a record folder and the user has filling capability on it, grant access to create the record
|
||||
if (checkConditions(destination, conditions) &&
|
||||
!recordFolderService.isRecordFolder(destination) )
|
||||
!recordFolderService.isRecordFolder(destination) &&
|
||||
permissionService.hasPermission(destination, CREATE_MODIFY_DESTROY_FILEPLAN_METADATA) == AccessStatus.ALLOWED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
|
||||
if (checkConditions(destination, conditions) &&
|
||||
recordFolderService.isRecordFolder(destination) &&
|
||||
permissionService.hasPermission(destination, RMPermissionModel.FILE_RECORDS) == AccessStatus.ALLOWED)
|
||||
permissionService.hasPermission(destination, FILE_RECORDS) == AccessStatus.ALLOWED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
@@ -147,7 +148,7 @@ public class CreateCapability extends DeclarativeCapability
|
||||
conditions.put("capabilityCondition.closed", Boolean.TRUE);
|
||||
if (checkConditions(destination, conditions) &&
|
||||
recordFolderService.isRecordFolder(destination) &&
|
||||
permissionService.hasPermission(getFilePlanService().getFilePlan(destination), RMPermissionModel.DECLARE_RECORDS_IN_CLOSED_FOLDERS) == AccessStatus.ALLOWED)
|
||||
permissionService.hasPermission(getFilePlanService().getFilePlan(destination), DECLARE_RECORDS_IN_CLOSED_FOLDERS) == AccessStatus.ALLOWED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
@@ -156,32 +157,32 @@ public class CreateCapability extends DeclarativeCapability
|
||||
conditions.put("capabilityCondition.cutoff", Boolean.TRUE);
|
||||
if (checkConditions(destination, conditions) &&
|
||||
recordFolderService.isRecordFolder(destination) &&
|
||||
permissionService.hasPermission(getFilePlanService().getFilePlan(destination), RMPermissionModel.CREATE_MODIFY_RECORDS_IN_CUTOFF_FOLDERS) == AccessStatus.ALLOWED)
|
||||
permissionService.hasPermission(getFilePlanService().getFilePlan(destination), CREATE_MODIFY_RECORDS_IN_CUTOFF_FOLDERS) == AccessStatus.ALLOWED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
}
|
||||
if (capabilityService.getCapability(RMPermissionModel.CREATE_MODIFY_DESTROY_FOLDERS).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
if (null != recordType && recordType.equals(TYPE_RECORD_FOLDER) && capabilityService.getCapability(CREATE_MODIFY_DESTROY_FOLDERS).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
if (capabilityService.getCapability(RMPermissionModel.DECLARE_RECORDS_IN_CLOSED_FOLDERS).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
if (capabilityService.getCapability(DECLARE_RECORDS_IN_CLOSED_FOLDERS).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
if (capabilityService.getCapability(RMPermissionModel.CREATE_MODIFY_RECORDS_IN_CUTOFF_FOLDERS).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
if (capabilityService.getCapability(CREATE_MODIFY_RECORDS_IN_CUTOFF_FOLDERS).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
if (capabilityService.getCapability(RMPermissionModel.CREATE_MODIFY_DESTROY_FILEPLAN_METADATA).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
if (capabilityService.getCapability(CREATE_MODIFY_DESTROY_FILEPLAN_METADATA).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
if (capabilityService.getCapability(RMPermissionModel.CREATE_HOLD).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
if (capabilityService.getCapability(CREATE_HOLD).evaluate(destination) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
if (((ChangeOrDeleteReferencesCapability)capabilityService.getCapability(RMPermissionModel.CHANGE_OR_DELETE_REFERENCES)).evaluate(destination, linkee) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
if (((ChangeOrDeleteReferencesCapability)capabilityService.getCapability(CHANGE_OR_DELETE_REFERENCES)).evaluate(destination, linkee) == AccessDecisionVoter.ACCESS_GRANTED)
|
||||
{
|
||||
return AccessDecisionVoter.ACCESS_GRANTED;
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@
|
||||
package org.alfresco.module.org_alfresco_module_rm.capability.policy;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.capability.impl.CreateCapability;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
@@ -42,10 +43,18 @@ public class CreatePolicy extends AbstractBasePolicy
|
||||
{
|
||||
NodeRef linkee = null;
|
||||
QName assocType = null;
|
||||
QName recordType = null;
|
||||
|
||||
// get the destination node
|
||||
NodeRef destination = getTestNode(invocation, params, cad.getParameters().get(0), cad.isParent());
|
||||
|
||||
//get the recordType
|
||||
for (Object qname : invocation.getArguments()) {
|
||||
if (qname != null && (qname.equals(RecordsManagementModel.TYPE_RECORD_FOLDER) || qname.equals(RecordsManagementModel.TYPE_RECORD_CATEGORY))) {
|
||||
recordType = (QName) qname;
|
||||
}
|
||||
}
|
||||
|
||||
if (cad.getParameters().size() > 1)
|
||||
{
|
||||
// get the linkee when present
|
||||
@@ -58,7 +67,7 @@ public class CreatePolicy extends AbstractBasePolicy
|
||||
}
|
||||
}
|
||||
|
||||
return ((CreateCapability) getCapabilityService().getCapability("Create")).evaluate(destination, linkee, assocType);
|
||||
return ((CreateCapability) getCapabilityService().getCapability("Create")).evaluate(destination, linkee, assocType, recordType);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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,9 +313,7 @@ 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 (!dsNextAction.getWriteMode().equals(WriteMode.READ_ONLY))
|
||||
if (isNotTrue((Boolean)nodeService.getProperty(action, PROP_MANUALLY_SET_AS_OF)) && !dsNextAction.getWriteMode().equals(WriteMode.READ_ONLY))
|
||||
{
|
||||
final String dispositionActionName = dsNextAction.getNextActionName();
|
||||
final Date dispositionActionDate = dsNextAction.getNextActionDateAsOf();
|
||||
@@ -342,7 +342,6 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
nodeService.setProperty(action, PROP_DISPOSITION_ACTION_NAME, dispositionActionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dsNodeRef = dsNextAction.getDispositionNodeRef();
|
||||
}
|
||||
@@ -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);
|
||||
@@ -383,6 +382,7 @@ 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. " +
|
||||
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().toString() + ")");
|
||||
}
|
||||
"(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)
|
||||
{
|
||||
if (hasDisposableItemsImpl(isRecordLevelDisposition, item));
|
||||
else if (filePlanService.isRecordCategory(item) && getAssociatedDispositionScheduleImpl(item) == null && hasDisposableItemsImpl(isRecordLevelDisposition, item))
|
||||
{
|
||||
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,17 +1103,14 @@ public class DispositionServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
|
||||
List<DispositionActionDefinition> dispositionActionDefinitions = dispositionSchedule.getDispositionActionDefinitions();
|
||||
DispositionActionDefinition currentDispositionActionDefinition = null;
|
||||
DispositionActionDefinition currentDispositionActionDefinition;
|
||||
DispositionActionDefinition nextDispositionActionDefinition = null;
|
||||
|
||||
if (currentDispositionAction == null)
|
||||
{
|
||||
if (!dispositionActionDefinitions.isEmpty())
|
||||
if (currentDispositionAction == null && !dispositionActionDefinitions.isEmpty())
|
||||
{
|
||||
// The next disposition action is the first action
|
||||
nextDispositionActionDefinition = dispositionActionDefinitions.get(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the current action
|
||||
@@ -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);
|
||||
@@ -1244,6 +1233,7 @@ 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;
|
||||
|
@@ -219,7 +219,7 @@ public class FilePlanServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
else
|
||||
{
|
||||
return rmContainerCacheManager.get(storeRef);
|
||||
return new HashSet<>(rmContainerCacheManager.get(storeRef));
|
||||
}
|
||||
|
||||
return results;
|
||||
|
@@ -111,6 +111,24 @@ public interface HoldService
|
||||
*/
|
||||
void setHoldReason(NodeRef hold, String reason);
|
||||
|
||||
/**
|
||||
* Sets the reason for the hold deletion
|
||||
*
|
||||
* @param hold The {@link NodeRef} of the hold
|
||||
* @param reason {@link String} The reason for the hold
|
||||
*/
|
||||
void setHoldDeletionReason(NodeRef hold, String reason);
|
||||
|
||||
/**
|
||||
* Updates a hold with the given name, reason and description
|
||||
*
|
||||
* @param hold The {@link NodeRef} of the hold
|
||||
* @param name {@link String} The name of the hold
|
||||
* @param reason {@link String} The reason of the hold
|
||||
* @param description {@link String} The description of the hold
|
||||
*/
|
||||
void updateHold(NodeRef hold, String name, String reason, String description);
|
||||
|
||||
/**
|
||||
* Deletes the hold
|
||||
*
|
||||
|
@@ -29,6 +29,7 @@ package org.alfresco.module.org_alfresco_module_rm.hold;
|
||||
|
||||
import static org.alfresco.model.ContentModel.ASPECT_LOCKABLE;
|
||||
import static org.alfresco.model.ContentModel.ASSOC_CONTAINS;
|
||||
import static org.alfresco.model.ContentModel.PROP_DESCRIPTION;
|
||||
import static org.alfresco.model.ContentModel.PROP_NAME;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -458,11 +459,11 @@ public class HoldServiceImpl extends ServiceBaseImpl
|
||||
|
||||
// create map of properties
|
||||
Map<QName, Serializable> properties = new HashMap<>(3);
|
||||
properties.put(ContentModel.PROP_NAME, name);
|
||||
properties.put(PROP_NAME, name);
|
||||
properties.put(PROP_HOLD_REASON, reason);
|
||||
if (description != null && !description.isEmpty())
|
||||
{
|
||||
properties.put(ContentModel.PROP_DESCRIPTION, description);
|
||||
properties.put(PROP_DESCRIPTION, description);
|
||||
}
|
||||
|
||||
// create assoc name
|
||||
@@ -512,6 +513,39 @@ public class HoldServiceImpl extends ServiceBaseImpl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#setHoldDeletionReason(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setHoldDeletionReason(NodeRef hold, String reason)
|
||||
{
|
||||
ParameterCheck.mandatory("hold", hold);
|
||||
ParameterCheck.mandatory("reason", reason);
|
||||
|
||||
if (nodeService.exists(hold) && isHold(hold))
|
||||
{
|
||||
nodeService.setProperty(hold, PROP_HOLD_DELETION_REASON, reason);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#updateHold(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String, java.lang.String) (org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void updateHold(NodeRef hold, String name, String reason, String description)
|
||||
{
|
||||
ParameterCheck.mandatory("hold", hold);
|
||||
ParameterCheck.mandatory("name", name);
|
||||
ParameterCheck.mandatory("reason", reason);
|
||||
|
||||
if (nodeService.exists(hold) && isHold(hold))
|
||||
{
|
||||
nodeService.setProperty(hold, PROP_NAME, name);
|
||||
nodeService.setProperty(hold, PROP_HOLD_REASON, reason);
|
||||
nodeService.setProperty(hold, PROP_DESCRIPTION, description);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.module.org_alfresco_module_rm.hold.HoldService#deleteHold(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@@ -563,7 +597,7 @@ public class HoldServiceImpl extends ServiceBaseImpl
|
||||
|
||||
if (permissionService.hasPermission(nodeRef, permission) == AccessStatus.DENIED)
|
||||
{
|
||||
heldNames.add((String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME));
|
||||
heldNames.add((String) nodeService.getProperty(nodeRef, PROP_NAME));
|
||||
}
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
@@ -630,7 +664,7 @@ public class HoldServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
if (!isHold(hold))
|
||||
{
|
||||
final String holdName = (String) nodeService.getProperty(hold, ContentModel.PROP_NAME);
|
||||
final String holdName = (String) nodeService.getProperty(hold, PROP_NAME);
|
||||
throw new IntegrityException(I18NUtil.getMessage("rm.hold.not-hold", holdName), null);
|
||||
}
|
||||
|
||||
@@ -688,7 +722,7 @@ public class HoldServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
if (!isRecordFolder(nodeRef) && !instanceOf(nodeRef, ContentModel.TYPE_CONTENT))
|
||||
{
|
||||
final String nodeName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
final String nodeName = (String) nodeService.getProperty(nodeRef, PROP_NAME);
|
||||
throw new IntegrityException(I18NUtil.getMessage("rm.hold.add-to-hold-invalid-type", nodeName), null);
|
||||
}
|
||||
|
||||
@@ -795,7 +829,7 @@ public class HoldServiceImpl extends ServiceBaseImpl
|
||||
{
|
||||
if (!isHold(hold))
|
||||
{
|
||||
final String holdName = (String) nodeService.getProperty(hold, ContentModel.PROP_NAME);
|
||||
final String holdName = (String) nodeService.getProperty(hold, PROP_NAME);
|
||||
throw new IntegrityException(I18NUtil.getMessage("rm.hold.not-hold", holdName), null);
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ import org.alfresco.service.namespace.QName;
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
@SuppressWarnings("PMD.ConstantsInInterface")
|
||||
@AlfrescoPublicApi
|
||||
public interface RecordsManagementModel extends RecordsManagementCustomModel
|
||||
{
|
||||
@@ -200,6 +201,7 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
|
||||
// Hold type
|
||||
QName TYPE_HOLD = QName.createQName(RM_URI, "hold");
|
||||
QName PROP_HOLD_REASON = QName.createQName(RM_URI, "holdReason");
|
||||
QName PROP_HOLD_DELETION_REASON = QName.createQName(RM_URI, "holdDeletionReason");
|
||||
//since 3.2
|
||||
@Deprecated
|
||||
QName ASSOC_FROZEN_RECORDS = QName.createQName(RM_URI, "frozenRecords");
|
||||
|
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* #%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.fileplans;
|
||||
|
||||
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.stream.Collectors;
|
||||
|
||||
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;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.resource.RelationshipResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rm.rest.api.impl.ApiNodesModelFactory;
|
||||
import org.alfresco.rm.rest.api.impl.FilePlanComponentsApiUtils;
|
||||
import org.alfresco.rm.rest.api.model.HoldModel;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* File plan holds relation
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@RelationshipResource(name = "holds", entityResource = FilePlanEntityResource.class, title = "Holds in a file plan")
|
||||
public class FilePlanHoldsRelation implements
|
||||
RelationshipResourceAction.Create<HoldModel>,
|
||||
RelationshipResourceAction.Read<HoldModel>,
|
||||
InitializingBean
|
||||
{
|
||||
private FilePlanComponentsApiUtils apiUtils;
|
||||
private ApiNodesModelFactory nodesModelFactory;
|
||||
private HoldService holdService;
|
||||
private FileFolderService fileFolderService;
|
||||
private TransactionService transactionService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
mandatory("apiUtils", this.apiUtils);
|
||||
mandatory("nodesModelFactory", this.nodesModelFactory);
|
||||
mandatory("holdService", this.holdService);
|
||||
mandatory("fileFolderService", this.fileFolderService);
|
||||
mandatory("transactionService", this.transactionService);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Return a paged list of holds for the file plan identified by 'filePlanId'")
|
||||
public CollectionWithPagingInfo<HoldModel> readAll(String filePlanId, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("filePlanId", filePlanId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef parentNodeRef = apiUtils.lookupAndValidateNodeType(filePlanId, RecordsManagementModel.TYPE_FILE_PLAN);
|
||||
List<NodeRef> holds = holdService.getHolds(parentNodeRef);
|
||||
|
||||
List<HoldModel> page = holds.stream()
|
||||
.map(hold -> fileFolderService.getFileInfo(hold))
|
||||
.map(nodesModelFactory::createHoldModel)
|
||||
.skip(parameters.getPaging().getSkipCount())
|
||||
.limit(parameters.getPaging().getMaxItems())
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
|
||||
int totalItems = holds.size();
|
||||
boolean hasMore = parameters.getPaging().getSkipCount() + parameters.getPaging().getMaxItems() < totalItems;
|
||||
return CollectionWithPagingInfo.asPaged(parameters.getPaging(), page, hasMore, totalItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Create one (or more) holds in a file plan identified by 'filePlanId'")
|
||||
public List<HoldModel> create(String filePlanId, List<HoldModel> holds, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("filePlanId", filePlanId);
|
||||
mandatory("holds", holds);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef parentNodeRef = apiUtils.lookupAndValidateNodeType(filePlanId, RecordsManagementModel.TYPE_FILE_PLAN);
|
||||
|
||||
RetryingTransactionCallback<List<NodeRef>> callback = () -> {
|
||||
List<NodeRef> createdNodes = new LinkedList<>();
|
||||
for (HoldModel nodeInfo : holds)
|
||||
{
|
||||
NodeRef newNodeRef = holdService.createHold(parentNodeRef, nodeInfo.name(), nodeInfo.reason(),
|
||||
nodeInfo.description());
|
||||
createdNodes.add(newNodeRef);
|
||||
}
|
||||
return createdNodes;
|
||||
};
|
||||
|
||||
List<NodeRef> createdNodes = transactionService.getRetryingTransactionHelper()
|
||||
.doInTransaction(callback, false, true);
|
||||
|
||||
return createdNodes.stream()
|
||||
.map(hold -> fileFolderService.getFileInfo(hold))
|
||||
.map(nodesModelFactory::createHoldModel)
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
}
|
||||
|
||||
public void setApiUtils(FilePlanComponentsApiUtils apiUtils)
|
||||
{
|
||||
this.apiUtils = apiUtils;
|
||||
}
|
||||
|
||||
public void setNodesModelFactory(ApiNodesModelFactory nodesModelFactory)
|
||||
{
|
||||
this.nodesModelFactory = nodesModelFactory;
|
||||
}
|
||||
|
||||
public void setHoldService(HoldService holdService)
|
||||
{
|
||||
this.holdService = holdService;
|
||||
}
|
||||
|
||||
public void setFileFolderService(FileFolderService fileFolderService)
|
||||
{
|
||||
this.fileFolderService = fileFolderService;
|
||||
}
|
||||
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* #%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.stream.Collectors;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
|
||||
import org.alfresco.repo.node.integrity.IntegrityException;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
|
||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
|
||||
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.HoldChild;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
/**
|
||||
* Hold children relation
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@RelationshipResource(name = "children", entityResource = HoldsEntityResource.class, title = "Children of a hold")
|
||||
public class HoldsChildrenRelation implements
|
||||
RelationshipResourceAction.Create<HoldChild>,
|
||||
RelationshipResourceAction.Read<HoldChild>,
|
||||
RelationshipResourceAction.Delete,
|
||||
InitializingBean
|
||||
{
|
||||
private HoldService holdService;
|
||||
private FilePlanComponentsApiUtils apiUtils;
|
||||
private ApiNodesModelFactory nodesModelFactory;
|
||||
private TransactionService transactionService;
|
||||
private FileFolderService fileFolderService;
|
||||
private PermissionService permissionService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
mandatory("holdService", holdService);
|
||||
mandatory("apiUtils", apiUtils);
|
||||
mandatory("nodesModelFactory", nodesModelFactory);
|
||||
mandatory("transactionService", transactionService);
|
||||
mandatory("fileFolderService", fileFolderService);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Add one (or more) children as children of a hold identified by 'holdId'")
|
||||
public List<HoldChild> create(String holdId, List<HoldChild> children, Parameters parameters)
|
||||
{
|
||||
// validate parameters
|
||||
checkNotBlank("holdId", holdId);
|
||||
mandatory("children", children);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef parentNodeRef = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
|
||||
RetryingTransactionCallback<List<NodeRef>> callback = () -> {
|
||||
List<NodeRef> createdNodes = children.stream()
|
||||
.map(holdChild -> new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, holdChild.id()))
|
||||
.collect(Collectors.toList());
|
||||
try
|
||||
{
|
||||
holdService.addToHold(parentNodeRef, createdNodes);
|
||||
}
|
||||
catch (IntegrityException exception)
|
||||
{
|
||||
// Throw 400 Bad Request when a node with id 'holdId' is not a hold or a child cannot be added to a hold
|
||||
throw new InvalidArgumentException(exception.getMsgId()).initCause(exception);
|
||||
}
|
||||
return createdNodes;
|
||||
};
|
||||
|
||||
List<NodeRef> nodeInfos = transactionService.getRetryingTransactionHelper()
|
||||
.doInTransaction(callback, false, true);
|
||||
|
||||
return nodeInfos.stream()
|
||||
.map(nodeRef -> new HoldChild(nodeRef.getId()))
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Return a paged list of hold children for the hold identified by 'holdId'")
|
||||
public CollectionWithPagingInfo<HoldChild> readAll(String holdId, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("holdId", holdId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef parentNodeRef = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
List<NodeRef> children = holdService.getHeld(parentNodeRef);
|
||||
|
||||
List<HoldChild> page = children.stream()
|
||||
.map(NodeRef::getId)
|
||||
.map(HoldChild::new)
|
||||
.skip(parameters.getPaging().getSkipCount())
|
||||
.limit(parameters.getPaging().getMaxItems())
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
|
||||
int totalItems = children.size();
|
||||
boolean hasMore = parameters.getPaging().getSkipCount() + parameters.getPaging().getMaxItems() < totalItems;
|
||||
return CollectionWithPagingInfo.asPaged(parameters.getPaging(), page, hasMore, totalItems);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Remove a child from a hold", description = "Remove a child with id 'childId' from a hold with id 'holdId'")
|
||||
public void delete(String holdId, String childId, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("holdId", holdId);
|
||||
checkNotBlank("childId", childId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef nodeRef = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
NodeRef childRef = apiUtils.lookupByPlaceholder(childId);
|
||||
|
||||
if (permissionService.hasReadPermission(childRef) == AccessStatus.DENIED)
|
||||
{
|
||||
throw new PermissionDeniedException(I18NUtil.getMessage("permissions.err_access_denied"));
|
||||
}
|
||||
|
||||
RetryingTransactionCallback<List<NodeRef>> callback = () -> {
|
||||
try
|
||||
{
|
||||
holdService.removeFromHold(nodeRef, childRef);
|
||||
}
|
||||
catch (IntegrityException exception)
|
||||
{
|
||||
// Throw 400 Bad Request when a node with id 'holdId' is not a hold
|
||||
throw new InvalidArgumentException(exception.getMsgId()).initCause(exception);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(callback, false, true);
|
||||
}
|
||||
|
||||
public void setHoldService(HoldService holdService)
|
||||
{
|
||||
this.holdService = holdService;
|
||||
}
|
||||
|
||||
public void setApiUtils(FilePlanComponentsApiUtils apiUtils)
|
||||
{
|
||||
this.apiUtils = apiUtils;
|
||||
}
|
||||
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
public void setNodesModelFactory(ApiNodesModelFactory nodesModelFactory)
|
||||
{
|
||||
this.nodesModelFactory = nodesModelFactory;
|
||||
}
|
||||
|
||||
public void setFileFolderService(FileFolderService fileFolderService)
|
||||
{
|
||||
this.fileFolderService = fileFolderService;
|
||||
}
|
||||
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* #%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 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;
|
||||
import org.alfresco.rest.framework.Operation;
|
||||
import org.alfresco.rest.framework.WebApiDescription;
|
||||
import org.alfresco.rest.framework.WebApiParam;
|
||||
import org.alfresco.rest.framework.resource.EntityResource;
|
||||
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
|
||||
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;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Hold entity resource
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@EntityResource(name = "holds", title = "Holds")
|
||||
public class HoldsEntityResource implements
|
||||
EntityResourceAction.ReadById<HoldModel>,
|
||||
EntityResourceAction.Update<HoldModel>,
|
||||
EntityResourceAction.Delete,
|
||||
InitializingBean
|
||||
{
|
||||
private FilePlanComponentsApiUtils apiUtils;
|
||||
private FileFolderService fileFolderService;
|
||||
private ApiNodesModelFactory nodesModelFactory;
|
||||
private HoldService holdService;
|
||||
private TransactionService transactionService;
|
||||
private HoldBulkService holdBulkService;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
mandatory("nodesModelFactory", nodesModelFactory);
|
||||
mandatory("apiUtils", apiUtils);
|
||||
mandatory("fileFolderService", fileFolderService);
|
||||
mandatory("holdService", holdService);
|
||||
mandatory("transactionService", transactionService);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Get hold information", description = "Get information for a hold with id 'holdId'")
|
||||
@WebApiParam(name = "holdId", title = "The hold id")
|
||||
public HoldModel readById(String holdId, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("holdId", holdId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef hold = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
FileInfo info = fileFolderService.getFileInfo(hold);
|
||||
return nodesModelFactory.createHoldModel(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Update a hold", description = "Updates a hold with id 'holdId'")
|
||||
public HoldModel update(String holdId, HoldModel holdModel, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("holdId", holdId);
|
||||
mandatory("holdModel", holdModel);
|
||||
mandatory("holdModel.name", holdModel.name());
|
||||
mandatory("holdModel.reason", holdModel.reason());
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef nodeRef = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
|
||||
RetryingTransactionCallback<Void> callback = () -> {
|
||||
holdService.updateHold(nodeRef, holdModel.name(), holdModel.reason(), holdModel.description());
|
||||
return null;
|
||||
};
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(callback, false, true);
|
||||
|
||||
RetryingTransactionCallback<FileInfo> readCallback = () -> fileFolderService.getFileInfo(nodeRef);
|
||||
FileInfo info = transactionService.getRetryingTransactionHelper().doInTransaction(readCallback, false, true);
|
||||
|
||||
return nodesModelFactory.createHoldModel(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
@WebApiDescription(title = "Delete hold", description = "Deletes a hold with id 'holdId'")
|
||||
public void delete(String holdId, Parameters parameters)
|
||||
{
|
||||
checkNotBlank("holdId", holdId);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef hold = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
RetryingTransactionCallback<Void> callback = () -> {
|
||||
holdService.deleteHold(hold);
|
||||
return null;
|
||||
};
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(callback, false, true);
|
||||
}
|
||||
|
||||
@Operation("delete")
|
||||
@WebApiDescription(title = "Delete hold with a reason",
|
||||
successStatus = HttpServletResponse.SC_OK)
|
||||
public HoldDeletionReason deleteHoldWithReason(String holdId, HoldDeletionReason reason, Parameters parameters,
|
||||
WithResponse withResponse)
|
||||
{
|
||||
checkNotBlank("holdId", holdId);
|
||||
mandatory("reason", reason);
|
||||
mandatory("parameters", parameters);
|
||||
|
||||
NodeRef hold = apiUtils.lookupAndValidateNodeType(holdId, RecordsManagementModel.TYPE_HOLD);
|
||||
String deletionReason = reason.reason();
|
||||
|
||||
RetryingTransactionCallback<Void> callback = () -> {
|
||||
if (StringUtils.isNotBlank(deletionReason))
|
||||
{
|
||||
holdService.setHoldDeletionReason(hold, deletionReason);
|
||||
}
|
||||
holdService.deleteHold(hold);
|
||||
return null;
|
||||
};
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(callback, false, true);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void setFileFolderService(FileFolderService fileFolderService)
|
||||
{
|
||||
this.fileFolderService = fileFolderService;
|
||||
}
|
||||
|
||||
public void setNodesModelFactory(ApiNodesModelFactory nodesModelFactory)
|
||||
{
|
||||
this.nodesModelFactory = nodesModelFactory;
|
||||
}
|
||||
|
||||
public void setHoldService(HoldService holdService)
|
||||
{
|
||||
this.holdService = holdService;
|
||||
}
|
||||
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
public void setHoldBulkService(HoldBulkService holdBulkService)
|
||||
{
|
||||
this.holdBulkService = holdBulkService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* #%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 Holds REST API
|
||||
*
|
||||
* @author Damian Ujma
|
||||
*/
|
||||
@WebApi(name="gs", scope=Api.SCOPE.PUBLIC, version=1)
|
||||
package org.alfresco.rm.rest.api.holds;
|
||||
import org.alfresco.rest.framework.Api;
|
||||
import org.alfresco.rest.framework.WebApi;
|
@@ -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;
|
||||
@@ -47,11 +53,14 @@ import org.alfresco.rest.api.model.UserInfo;
|
||||
import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rm.rest.api.model.FilePlan;
|
||||
import org.alfresco.rm.rest.api.model.HoldModel;
|
||||
import org.alfresco.rm.rest.api.model.RMNode;
|
||||
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;
|
||||
@@ -60,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;
|
||||
@@ -69,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
|
||||
@@ -80,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);
|
||||
|
||||
@@ -101,6 +118,7 @@ public class ApiNodesModelFactory
|
||||
private PersonService personService;
|
||||
private DispositionService dispositionService;
|
||||
private ServiceRegistry serviceRegistry;
|
||||
private RecordsManagementServiceRegistry services;
|
||||
|
||||
public NodeService getNodeService()
|
||||
{
|
||||
@@ -152,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.
|
||||
*
|
||||
@@ -503,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));
|
||||
}
|
||||
@@ -522,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);
|
||||
}
|
||||
@@ -535,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
|
||||
@@ -564,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);
|
||||
@@ -637,6 +676,21 @@ public class ApiNodesModelFactory
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an object of type HoldModel
|
||||
*
|
||||
* @param info info of the hold
|
||||
* @return HoldModel object
|
||||
*/
|
||||
public HoldModel createHoldModel(FileInfo info)
|
||||
{
|
||||
return new HoldModel(info.getNodeRef().getId(),
|
||||
(String) info.getProperties().get(ContentModel.PROP_NAME),
|
||||
(String) info.getProperties().get(ContentModel.PROP_DESCRIPTION),
|
||||
(String) info.getProperties().get(RecordsManagementModel.PROP_HOLD_REASON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object of type FilePlan
|
||||
*
|
||||
@@ -875,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) {
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user