diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000000..bc34200905
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,73 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at katalin.zanaty@alfresco.com. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..1ec3fe91f5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,140 @@
+# Records Management: README
+
+## Contributing
+Please refer to our [How to contribute](/CONTRIBUTING.md) guide and our [Contributor Covenant Code of Conduct](/CODE_OF_CONDUCT.md).
+
+## Configuring and starting Alfresco/Share
+* Clone the project (e.g. `git clone git@gitlab.alfresco.com:records-management/records-management.git`)
+* Import the project as a maven project
+* Start the Alfresco/Share instances with the following commands:
+
+ ```
+ mvn clean install -Pstart-repo
+ mvn clean install -Pstart-share
+ ```
+
+ (these commands work best if run from the specific directories, e.g. start Share from
+ rm-community/rm-community-share/ or rm-enterprise/rm-enterprise-share/ )
+
+## Configuring a different DB other than H2 (e.g. MySQL or PostgreSQL)
+* Create a file called _local.properties_ under src/main/resources in alfresco-rm-enterprise-repo
+* Add the following properties in this new file
+
+ ```
+ my.db.name -> The name of the database schema
+ my.db.port -> The port number for your database (default port number for postgres is 5432 and for mysql it is 3306)
+ ```
+* Run the following commands to start your Alfresco instance:
+
+ to start Alfresco (using Postgres):
+ ```
+ mvn clean install -Pstart-repo,use-postgres
+ ```
+
+ to start Alfresco (using MySQL):
+
+ ```
+ mvn clean install -Pstart-repo,use-mysql
+ ```
+
+## Technical documentation
+Technical documentation is available at [rm-community/documentation/README.md](/rm-community/documentation/README.md) and [rm-enterprise/documentation/README.md](/rm-enterprise/documentation/README.md). This should be particularly useful for anyone wanting to integrate with or extend RM.
+
+## Running integration test
+In order to execute the integration tests run the following command (unit tests will be executed every time before you start Alfresco/Share):
+
+```
+mvn clean install -Dskip.integrationtests=false
+```
+
+## Running UI Automation tests
+To run the automated UI tests, change to the rm-automation directory and run:
+
+```
+mvn clean install -Dskip.automationtests=false
+```
+
+Note: due to Selenium Firefox driver changes, the highest supported Firefox version for UI tests is 43.0.4 (with Selenium 2.52.0).
+
+It is possible to have multiple versions of Firefox installed onto your workstation (e.g. one for running the UI tests and the other, kept
+up to date, for everyday browsing) but beware Firefox auto-updates. In this scenario the best approach is to create a non-default profile
+(default profiles will be shared between your Firefox installations!) for which auto-updates are disabled and forcing the use of this
+profile in your tests (`-Dwebdriver.firefox.profile="ProfileName"`). If your Firefox 43 install isn't in your path, you can use the
+`-Dwebdriver.firefox.profile` option set to the full path of its "firefox-bin" executable.
+
+MacOS X Sierra users: if you experience by order of magnitude slower performance when connected to a WiFi network (e.g. office WiFi)
+add your workstation to your local /etc/hosts file as described on https://github.com/SeleniumHQ/selenium/issues/2824.
+
+To use Chrome instead of Firefox:
+1. copy webdriver.properties from https://github.com/AlfrescoTestAutomation/selenium-grid/tree/master/src/main/resources
+2. put it under src/test/resource in rm-automation-ui project
+3. download the chrome driver from http://chromedriver.storage.googleapis.com and extract it
+4. change the following properties in webdriver.properties: webdriver.browser (Chrome) and webdriver.chrome.server.path (path/to/chrome/driver)
+5. run the tests as usual
+
+## Updating License Headers
+In order to refesh out of date license source headers run the following command:
+
+```
+mvn clean install -Dlicense.update.dryrun=false
+```
+
+## Running tests against latest Aikau snapshot
+The latest Aikau snapshot can be pulled by running the following command in rm-community:
+
+```
+mvn clean install -DskipTests -Dalfresco.aikau.version=LATEST -U
+```
+
+Thereafter start the Share instance and run automation tests as described above.
+
+## Configuring Outlook Integration
+To download and run RM with the Outlook Integration AMPs installed on the repo and Share use the following commands:
+
+```
+mvn clean install -Pstart-repo,outlook-integration
+mvn clean install -Pstart-share,outlook-integration
+```
+
+Follow these instructions to install licence and Outlook plugin:
+
+* http://docs.alfresco.com/outlook2.1/tasks/Outlook-license.html
+* http://docs.alfresco.com/outlook2.1/tasks/Outlook-install_v2.html
+
+## SNAPSHOT dependencies
+If you're building Enterprise RM, the base project (Community) is pulled in via a snapshot dependency configured in maven.
+This dependency will either be loaded from your local .m2 cache, or from Nexus if the version in your .m2 doesn't exist or is old
+('old' in maven terms is anything over 24 hours old). If maven fetches community dependencies from Nexus, then it's unlikely to contain your changes.
+You want to always use the version in your local cache - this means either doing a daily build at the root project level
+that pushes a new copy of the correct version into your cache, or alternatively you could run mvn with the
+`--no-snapshot-dependency` (or `-nsu`) option, which won't try to download a newer version.
+
+## Code Formatting
+This project follows the usual Alfresco Coding Standards. If you use Eclipse or IntelliJ, there are settings inside the ide-config directory for you to import.
+
+## Surf build errors
+If you get:
+```
+[ERROR] Failed to execute goal on project alfresco-rm-community-share: Could not resolve dependencies for project org.alfresco:alfresco-rm-community-share:amp:2.6-SNAPSHOT: Failed to collect dependencies at org.alfresco.surf:spring-surf-api:jar:6.3 -> org.alfresco.surf:spring-surf:jar:${dependency.surf.version}: Failed to read artifact descriptor for org.alfresco.surf:spring-surf:jar:${dependency.surf.version}: Could not transfer artifact org.alfresco.surf:spring-surf:pom:${dependency.surf.version} from/to alfresco-internal (https://artifacts.alfresco.com/nexus/content/groups/private): Not authorized , ReasonPhrase:Unauthorized. -> [Help 1]
+```
+
+then please re-run with `-Ddependency.surf.version=6.3`
+
+## Install lombok plugin for IDEs
+To allow automation and benchmark projects to be built within an IDE the lombok 'plugin' needs to be installed.
+Execute lombok.jar (doubleclick it, or run `java -jar lombok.jar`). Follow the instructions.
+
+## Use Solr 6 with Alfresco 5.2.x
+In alfresco-global.properties (depending on the RM edition `/records-management/rm-community/rm-community-repo/src/test/properties/local` or `/records-management/rm-enterprise/rm-enterprise-repo/src/test/properties/local`)
+change the value for "index.subsystem.name" from "solr4" to "solr6".
+Add also the following property "solr.port=8983".
+
+Download the latest Alfresco Search Services from
+[https://nexus.alfresco.com/nexus/#nexus-search;gav\~\~alfresco-search-services\~\~\~](https://nexus.alfresco.com/nexus/#nexus-search;gav~~alfresco-search-services~~~)
+Currently it's 1.0.0 (alfresco-search-services-1.0.0.zip)
+
+Unzip it and change to the "solr" folder within it. Start the Solr server using the following command:
+```
+solr start -a "-Dcreate.alfresco.defaults=alfresco,archive"
+```
+Start your repository
diff --git a/README.txt b/README.txt
deleted file mode 100644
index 1d260c7466..0000000000
--- a/README.txt
+++ /dev/null
@@ -1,155 +0,0 @@
-Configuring and starting Alfresco/Share:
-----------------------------------------
-
-- Clone the project (e.g. git clone git@gitlab.alfresco.com:records-management/records-management.git)
-
-- Import the project as a maven project
-
-- Start the Alfresco/Share instances with the following commands:
-
- mvn clean install -Pstart-repo
- mvn clean install -Pstart-share
-
- (these commands work best if run from the specific directories, e.g. start share from
- rm-enterprise/rm-enterprise-share/ or rm-community/rm-community-share/ )
-
-
-Configuring a different DB other than H2 (e.g. MySQL or PostgreSQL):
---------------------------------------------------------------------
-
-- Create a file called "local.properties" under src/main/resources in alfresco-rm-enterprise-repo
-
-- Add the following properties in this new file
- my.db.name -> The name of the database schema
- my.db.port -> The port number for your database (default port number for postgres is 5432 and for mysql it is 3306)
-
-- Run the following commands to start your Alfresco instance:
-
- to start Alfresco (using Postgres):
- mvn clean install -Pstart-repo,use-postgres
-
- to start Alfresco (using MySQL):
- mvn clean install -Pstart-repo,use-mysql
-
-
-Technical documentation:
-------------------------
-
-Technical documentation is available at rm-community/documentation/README.md and rm-enterprise/documentation/README.md.
-This should be particularly useful for anyone wanting to integrate with or extend RM.
-
-
-Running integration test:
--------------------------
-
-In order to execute the integration tests run the following command (unit tests will be executed every time before you start Alfresco/Share):
-
-mvn clean install -Dskip.integrationtests=false
-
-
-Running UI Automation tests:
-----------------------------
-
-To run the automated UI tests, change to the rm-automation directory and run:
-
- mvn clean install -Dskip.automationtests=false
-
-Note: due to Selenium Firefox driver changes, the highest supported Firefox version for UI tests is 43.0.4 (with Selenium 2.52.0).
-
-It is possible to have multiple versions of Firefox installed onto your workstation (e.g. one for running the UI tests and the other, kept
-up to date, for everyday browsing) but beware Firefox auto-updates. In this scenario the best approach is to create a non-default profile
-(default profiles will be shared between your Firefox installations!) for which auto-updates are disabled and forcing the use of this
-profile in your tests (-Dwebdriver.firefox.profile="ProfileName"). If your Firefox 43 install isn't in your path, you can use the
--Dwebdriver.firefox.profile option set to the full path of its "firefox-bin" executable.
-
-MacOS X Sierra users: if you experience by order of magnitude slower performance when connected to a WiFi network (e.g. office WiFi)
-add your workstation to your local /etc/hosts file as described on https://github.com/SeleniumHQ/selenium/issues/2824.
-
-To use Chrome instead of Firefox:
- - copy webdriver.properties from https://github.com/AlfrescoTestAutomation/selenium-grid/tree/master/src/main/resources
- - put it under src/test/resource in rm-automation-ui project
- - download the chrome driver from http://chromedriver.storage.googleapis.com/ and extract it
- - change the following properties in webdriver.properties: webdriver.browser (Chrome) and webdriver.chrome.server.path (path/to/chrome/driver)
- - run the tests as usual
-
-
-Updating License Headers:
--------------------------
-
-In order to refesh out of date license source headers run the following command:
-
-mvn clean install -Dlicense.update.dryrun=false
-
-
-Running tests against latest Aikau snapshot:
---------------------------------------------
-
-The latest Aikau snapshot can be pulled by running the following command in rm-community:
-
- mvn clean install -DskipTests -Dalfresco.aikau.version=LATEST -U
-
-Thereafter start the Share instance and run automation tests as described above.
-
-
-Configuring Outlook Integration:
--------------------------------
-
-To download and run RM with the Outlook Integration AMPs installed on the repo and Share use the following commands:
-
- mvn clean install -Pstart-repo,outlook-integration
- mvn clean install -Pstart-share,outlook-integration
-
-Follow these instructions install licence and Outlook plugin:
-
- - http://docs.alfresco.com/outlook2.1/tasks/Outlook-license.html
- - http://docs.alfresco.com/outlook2.1/tasks/Outlook-install_v2.html
-
-
-SNAPSHOT dependencies:
-----------------------
-
-If you're building Enterprise RM, the base project (Community) is pulled in via a snapshot dependency configured in maven.
-This dependency will either be loaded from your local .m2 cache or from Nexus if the version in your .m2 doesn't exist or is old
-(Old in maven terms is anything over 24hrs old). If maven fetches it from Nexus, your code it's unlikely to be the correct version.
-You want to always use the version in your local cache - this means either doing a daily build at the root project level
-that pushes a new copy of the correct version into your cache, or alternatively you could run mvn with the
---no-snapshot-dependency (or -nsu) option, which won't try to download a newer version.
-
-
-Code Formatting:
-----------------
-
-This project follows the usual Alfresco Coding Standards. If you use Eclipse or IntelliJ, there are settings inside the ide-config directory for you to import.
-
-
-Surf build errors:
-------------------
-
-If you get:
-[ERROR] Failed to execute goal on project alfresco-rm-community-share: Could not resolve dependencies for project org.alfresco:alfresco-rm-community-share:amp:2.6-SNAPSHOT: Failed to collect dependencies at org.alfresco.surf:spring-surf-api:jar:6.3 -> org.alfresco.surf:spring-surf:jar:${dependency.surf.version}: Failed to read artifact descriptor for org.alfresco.surf:spring-surf:jar:${dependency.surf.version}: Could not transfer artifact org.alfresco.surf:spring-surf:pom:${dependency.surf.version} from/to alfresco-internal (https://artifacts.alfresco.com/nexus/content/groups/private): Not authorized , ReasonPhrase:Unauthorized. -> [Help 1]
-
-then please re-run with -Ddependency.surf.version=6.3
-
-
-Install lombok plugin for IDEs:
--------------------------------
-
-To allow automation and benchmark projects to be built within an IDE the lombok 'plugin' needs to be installed.
-
-Execute lombok.jar (doubleclick it, or run java -jar lombok.jar). Follow instructions.
-
-
-Use Solr 6 with Alfresco 5.2.x:
--------------------------------
-In alfresco-global.properties (depending on the RM edition /records-management/rm-community/rm-community-repo/src/test/properties/local or /records-management/rm-enterprise/rm-enterprise-repo/src/test/properties/local)
-change the value for "index.subsystem.name" from "solr4" to "solr6".
-Add also the following property "solr.port=8983".
-
-Download the latest Alfresco Search Services from
-https://nexus.alfresco.com/nexus/#nexus-search;gav~~alfresco-search-services~~~
-Currently it's 1.0.0 (alfresco-search-services-1.0.0.zip)
-
-Unzip it and change to the "solr" folder within it. Start the Solr server using the following command:
-solr start -a "-Dcreate.alfresco.defaults=alfresco,archive"
-
-Start your repository
diff --git a/pom.xml b/pom.xml
index 1858f130d1..5d5169f3ac 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
org.alfrescoalfresco-rmpom
- 2.6.3-SNAPSHOT
+ 2.7.3-SNAPSHOTAlfresco Records Management
@@ -24,7 +24,7 @@
scm:git:https://git.alfresco.com/records-management/records-management.gitscm:git:https://git.alfresco.com/records-management/records-management.githttps://git.alfresco.com/records-management/records-management
- HEAD
+ HEAD
diff --git a/rm-automation/pom.xml b/rm-automation/pom.xml
index 13b5157af8..13198cafdc 100644
--- a/rm-automation/pom.xml
+++ b/rm-automation/pom.xml
@@ -8,7 +8,7 @@
org.alfrescoalfresco-rm
- 2.6.3-SNAPSHOT
+ 2.7.3-SNAPSHOT
diff --git a/rm-automation/rm-automation-community-rest-api/pom.xml b/rm-automation/rm-automation-community-rest-api/pom.xml
index 68715e4554..9e5f413a04 100644
--- a/rm-automation/rm-automation-community-rest-api/pom.xml
+++ b/rm-automation/rm-automation-community-rest-api/pom.xml
@@ -8,7 +8,7 @@
org.alfrescoalfresco-rm-automation
- 2.6.3-SNAPSHOT
+ 2.7.3-SNAPSHOT
diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java
index 5fbc949a45..20acd4cf57 100644
--- a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java
+++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/BaseAPI.java
@@ -121,6 +121,37 @@ public abstract class BaseAPI
return results;
}
+ /**
+ * Helper method to extract the property value for the given nodeRef and property name
+ *
+ * @param result
+ * @param nodeRef
+ * @param propertyName
+ * @return
+ */
+ protected String getPropertyValue(JSONObject result, String nodeRef, String propertyName)
+ {
+ String propertyValue = "";
+ try
+ {
+ JSONArray items = result.getJSONArray("items");
+ for (int i = 0; i < items.length(); i++)
+ {
+ JSONObject item = items.getJSONObject(i);
+ if(nodeRef.equals(item.getString("nodeRef")))
+ {
+ propertyValue = item.getJSONObject("properties").getString(propertyName);
+ }
+ }
+ }
+ catch (JSONException error)
+ {
+ throw new RuntimeException("Unable to parse result", error);
+ }
+
+ return propertyValue;
+ }
+
/**
* Helper method to extract property values from request result and put them in map as a list that corresponds to a unique property value.
*
@@ -310,6 +341,78 @@ public abstract class BaseAPI
}
}
+ /**
+ * Helper method for PUT requests
+ *
+ * @param adminUser user with administrative privileges
+ * @param adminPassword password for adminUser
+ * @param expectedStatusCode The expected return status code.
+ * @param requestParams zero or more endpoint specific request parameters
+ * @param urlTemplate request URL template
+ * @param urlTemplateParams zero or more parameters used with urlTemplate
+ */
+ protected HttpResponse doPutJsonRequest(String adminUser,
+ String adminPassword,
+ int expectedStatusCode,
+ JSONObject requestParams,
+ String urlTemplate,
+ String... urlTemplateParams)
+ {
+ AlfrescoHttpClient client = alfrescoHttpClientFactory.getObject();
+ return doPutJsonRequest(adminUser, adminPassword, expectedStatusCode, client.getApiUrl(), requestParams, urlTemplate, urlTemplateParams);
+ }
+
+ /**
+ * Helper method for PUT requests
+ *
+ * @param adminUser user with administrative privileges
+ * @param adminPassword password for adminUser
+ * @param expectedStatusCode The expected return status code.
+ * @param urlStart the start of the URL (for example "alfresco/s/slingshot").
+ * @param requestParams zero or more endpoint specific request parameters
+ * @param urlTemplate request URL template
+ * @param urlTemplateParams zero or more parameters used with urlTemplate
+ * @throws AssertionError if the returned status code is not as expected.
+ */
+ private HttpResponse doPutJsonRequest(String adminUser,
+ String adminPassword,
+ int expectedStatusCode,
+ String urlStart,
+ JSONObject requestParams,
+ String urlTemplate,
+ String... urlTemplateParams)
+ {
+ String requestUrl = formatRequestUrl(urlStart, urlTemplate, urlTemplateParams);
+ try
+ {
+ HttpResponse httpResponse = doRequestJson(HttpPut.class, requestUrl, adminUser, adminPassword, requestParams);
+ assertEquals("PUT request to " + requestUrl + " was not successful.", expectedStatusCode, httpResponse.getStatusLine().getStatusCode());
+ return httpResponse;
+ }
+ catch (InstantiationException | IllegalAccessException error)
+ {
+ throw new IllegalArgumentException("doPutRequest failed", error);
+ }
+ }
+
+ /**
+ * Fill in the parameters for a URL template.
+ *
+ * @param urlStart The start of the URL.
+ * @param urlTemplate The template.
+ * @param urlTemplateParams Any parameters that need to be filled into the URL template.
+ * @return The resultant URL.
+ */
+ private String formatRequestUrl(String urlStart, String urlTemplate, String[] urlTemplateParams)
+ {
+ if (urlTemplateParams.length == 1)
+ {
+ // The format method needs some help to know not to use the whole array object.
+ return MessageFormat.format(urlTemplate, urlStart, urlTemplateParams[0]);
+ }
+ return MessageFormat.format(urlTemplate, urlStart, urlTemplateParams);
+ }
+
/**
* Helper method for POST requests
* @param adminUser user with administrative privileges
@@ -403,15 +506,12 @@ public abstract class BaseAPI
String urlTemplate,
String... urlTemplateParams)
{
- // Ensure the host is part of the request URL.
- String requestUrl = MessageFormat.format(
- urlTemplate,
- urlStart,
- urlTemplateParams);
+ String requestUrl;
+ requestUrl = formatRequestUrl(urlStart, urlTemplate, urlTemplateParams);
try
{
HttpResponse httpResponse = doRequestJson(HttpPost.class, requestUrl, adminUser, adminPassword, requestParams);
- assertEquals("POST request to " + requestUrl + " was not successful.", httpResponse.getStatusLine().getStatusCode(), expectedStatusCode);
+ assertEquals("POST request to " + requestUrl + " was not successful.", expectedStatusCode, httpResponse.getStatusLine().getStatusCode());
return httpResponse;
}
catch (InstantiationException | IllegalAccessException error)
@@ -453,7 +553,10 @@ public abstract class BaseAPI
{
((HttpEntityEnclosingRequestBase) request).setEntity(new StringEntity(requestParams.toString()));
}
+ LOGGER.info("Sending {} request to {}", requestType.getSimpleName(), requestUrl);
+ LOGGER.info("Request body: {}", requestParams);
response = client.execute(adminUser, adminPassword, request);
+ LOGGER.info("Response: {}", response.getStatusLine());
try
{
@@ -573,6 +676,9 @@ public abstract class BaseAPI
SHELF,
BOX,
FILE,
+ ORIGINATOR,
+ ORIGINATING_ORGANIZATION,
+ PUBLICATION_DATE
}
public enum RETENTION_SCHEDULE
@@ -587,7 +693,7 @@ public abstract class BaseAPI
RETENTION_GHOST,
RETENTION_ELIGIBLE_FIRST_EVENT,
RETENTION_EVENTS,
-
+ COMBINE_DISPOSITION_STEP_CONDITIONS
}
/**
@@ -599,6 +705,8 @@ public abstract class BaseAPI
CUT_OFF("cutoff"),
UNDO_CUT_OFF("undoCutoff"),
TRANSFER("transfer"),
+ COMPLETE_EVENT("completeEvent"),
+ UNDO_EVENT("undoEvent"),
DESTROY("destroy");
String action;
diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/RMEvents.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/RMEvents.java
new file mode 100644
index 0000000000..e54c5536de
--- /dev/null
+++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/core/v0/RMEvents.java
@@ -0,0 +1,49 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.rest.core.v0;
+
+public enum RMEvents
+{
+ ABOLISHED("abolished"),
+ ALL_ALLOWANCES_GRANTED_ARE_TERMINATED("all_allowances_granted_are_terminated"),
+ CASE_CLOSED("case_closed"),
+ DECLASSIFICATION_REVIEW("declassification_review"),
+ OBSOLETE("obsolete"),
+ NO_LONGER_NEEDED("no_longer_needed"),
+ STUDY_COMPLETE("study_complete");
+ private String eventName;
+
+ RMEvents(String eventName)
+ {
+ this.eventName = eventName;
+ }
+
+ public String getEventName()
+ {
+ return eventName;
+ }
+}
diff --git a/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/audit/AuditEntry.java b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/audit/AuditEntry.java
new file mode 100644
index 0000000000..117f13fb76
--- /dev/null
+++ b/rm-automation/rm-automation-community-rest-api/src/main/java/org/alfresco/rest/rm/community/model/audit/AuditEntry.java
@@ -0,0 +1,89 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.rest.rm.community.model.audit;
+
+import java.util.List;
+
+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 audit entry
+ *
+ * @author Rodica Sutu
+ * @since 2.7
+ */
+@Builder
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonIgnoreProperties (ignoreUnknown = true)
+public class AuditEntry extends TestModel
+{
+ @JsonProperty (required = true)
+ private String nodeName;
+
+ @JsonProperty (required = true)
+ private Listrma:filePlanComponent
@@ -1130,6 +1136,19 @@
false
+
+ d:date
+ true
+
+
+ d:text
+ true
+
+ true
+ false
+ false
+
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsPermissionModel.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsPermissionModel.xml
index d545517f44..9f9dc70b2e 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsPermissionModel.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsPermissionModel.xml
@@ -490,8 +490,8 @@
-
-
+
+
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
index 63242f2ab1..1ee6caf7e9 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/module-context.xml
@@ -248,6 +248,12 @@
+
+
+
+
+
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-context.xml
index 7ca1fc7bab..6d4c60152e 100755
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-context.xml
@@ -46,6 +46,7 @@
+
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml
index d6ebbeca54..766842f0a8 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml
@@ -3,10 +3,10 @@
-
-
-
-
+
+
+
+
@@ -17,11 +17,14 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMapConfig.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMapConfig.xml
index 8144e44bf6..fd97f207cb 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMapConfig.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMapConfig.xml
@@ -2,6 +2,11 @@
+
+
+
+
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-audit-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-audit-context.xml
index 61c53f3c6b..b7c7ce514e 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-audit-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-audit-context.xml
@@ -53,10 +53,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
index ddd303c982..a3a01f47b0 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
@@ -143,6 +143,7 @@
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index de5519decd..32ea68a220 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -933,6 +933,7 @@
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
index 3c12a64720..2cc9710263 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
@@ -20,6 +20,7 @@
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-version-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-version-context.xml
index 91c2f622ea..f9f7a7e409 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-version-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-version-context.xml
@@ -16,6 +16,7 @@
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml
index 0215c04957..05a062c994 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml
@@ -466,8 +466,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ ${audit.rm.viewLog.maxSize}
+
diff --git a/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/rma/dispositionactiondefinition.lib.ftl b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/rma/dispositionactiondefinition.lib.ftl
index 765b823b15..b936241f81 100644
--- a/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/rma/dispositionactiondefinition.lib.ftl
+++ b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/rma/dispositionactiondefinition.lib.ftl
@@ -37,6 +37,7 @@
<#if action.period??>"period": "${action.period}",#if>
<#if action.periodProperty??>"periodProperty": "${action.periodProperty}",#if>
<#if action.location??>"location": "${action.location}",#if>
+ <#if action.combineDispositionStepConditions??>"combineDispositionStepConditions": "${action.combineDispositionStepConditions?string}",#if>
<#if action.events??>"events": [<#list action.events as event>"${event}"<#if event_has_next>,#if>#list>],#if>
"eligibleOnFirstCompleteEvent": ${action.eligibleOnFirstCompleteEvent?string}
}
diff --git a/rm-community/rm-community-repo/pom.xml b/rm-community/rm-community-repo/pom.xml
index b53480d311..0b7c2d62bc 100644
--- a/rm-community/rm-community-repo/pom.xml
+++ b/rm-community/rm-community-repo/pom.xml
@@ -9,7 +9,7 @@
org.alfrescoalfresco-rm-community
- 2.6.3-SNAPSHOT
+ 2.7.3-SNAPSHOT
@@ -25,8 +25,6 @@
alfresco-rm-community-repotrue${project.build.directory}/solr/home
-
- 5.1.11.4
@@ -364,7 +362,7 @@
${alfresco.groupId}alfresco-repository
- ${alfresco.h2scripts.version}
+ ${alfresco.version}h2scripts
@@ -615,7 +613,7 @@
${alfresco.groupId}alfresco-repository
- ${alfresco.h2scripts.version}
+ ${alfresco.version}h2scripts
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/BroadcastDispositionActionDefinitionUpdateAction.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/BroadcastDispositionActionDefinitionUpdateAction.java
index de2bda630d..9e68395cef 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/BroadcastDispositionActionDefinitionUpdateAction.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/BroadcastDispositionActionDefinitionUpdateAction.java
@@ -253,7 +253,7 @@ public class BroadcastDispositionActionDefinitionUpdateAction extends RMActionEx
{
NodeRef dispositionedNode = getNodeService().getPrimaryParent(nextAction.getNodeRef()).getParentRef();
DispositionActionDefinition definition = nextAction.getDispositionActionDefinition();
- Date newAsOfDate = getDispositionService().calculateAsOfDate(dispositionedNode, definition, false);
+ Date newAsOfDate = getDispositionService().calculateAsOfDate(dispositionedNode, definition);
if (logger.isDebugEnabled())
{
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java
index ee08ee4c73..bf18587423 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java
@@ -876,15 +876,11 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas
}
String lovConstraintQNameAsString = newLovConstraint.toPrefixString(getNamespaceService());
- // Add the constraint - if it isn't already there.
- String refOfExistingConstraint = null;
+ // Add the constraint - if it isn't already there (there should only be one constraint).
+ String refOfExistingConstraint = (targetProp.getConstraints().isEmpty() ?
+ null :
+ targetProp.getConstraints().get(0).getRef());
- for (M2Constraint c : targetProp.getConstraints())
- {
- // There should only be one constraint.
- refOfExistingConstraint = c.getRef();
- break;
- }
if (refOfExistingConstraint != null)
{
targetProp.removeConstraintRef(refOfExistingConstraint);
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
index 2f79064e2d..8af59833ee 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
@@ -27,6 +27,14 @@
package org.alfresco.module.org_alfresco_module_rm.audit;
+import static org.alfresco.model.ContentModel.PROP_AUTHORITY_DISPLAY_NAME;
+import static org.alfresco.model.ContentModel.PROP_AUTHORITY_NAME;
+import static org.alfresco.model.ContentModel.PROP_USERNAME;
+import static org.alfresco.module.org_alfresco_module_rm.audit.event.UserGroupMembershipUtils.PARENT_GROUP;
+import static org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model.TYPE_DOD_5015_SITE;
+import static org.alfresco.module.org_alfresco_module_rm.model.rma.type.RmSiteType.DEFAULT_SITE_NAME;
+import static org.apache.commons.lang3.StringUtils.isBlank;
+
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
@@ -43,6 +51,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import javax.transaction.SystemException;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
@@ -72,6 +81,8 @@ import org.alfresco.service.cmr.repository.MLText;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AccessStatus;
+import org.alfresco.service.cmr.site.SiteInfo;
+import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
@@ -186,6 +197,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
private DictionaryService dictionaryService;
private TransactionService transactionService;
private NodeService nodeService;
+ private SiteService siteService;
private ContentService contentService;
private AuditComponent auditComponent;
private AuditService auditService;
@@ -237,6 +249,13 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
this.nodeService = nodeService;
}
+ /**
+ * Set the site service (used to check the type of RM site created).
+ *
+ * @param siteService The site service.
+ */
+ public void setSiteService(SiteService siteService) { this.siteService = siteService; }
+
/**
* Sets the ContentService instance
*/
@@ -713,7 +732,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
*
* @param auditedNodes details of the nodes that were modified
*/
- private void auditInTxn(Set auditedNodes) throws Throwable
+ private void auditInTxn(Set auditedNodes) throws SystemException
{
// Go through all the audit information and audit it
boolean auditedSomething = false;
@@ -820,7 +839,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
* @param writer Writer to write the audit trail
* @param reportFormat Format to write the audit trail in, ignored if writer is null
*/
- private void getAuditTrailImpl(
+ protected void getAuditTrailImpl(
final RecordsManagementAuditQueryParameters params,
final List results,
final Writer writer,
@@ -967,9 +986,10 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
return true;
}
- if(nodeRef != null && nodeService.exists(nodeRef) &&
- !AccessStatus.ALLOWED.equals(
- capabilityService.getCapabilityAccessState(nodeRef, ACCESS_AUDIT_CAPABILITY)))
+ if (nodeRef != null && nodeService.exists(nodeRef) &&
+ filePlanService.isFilePlanComponent(nodeRef) &&
+ !AccessStatus.ALLOWED.equals(
+ capabilityService.getCapabilityAccessState(nodeRef, ACCESS_AUDIT_CAPABILITY)))
{
return true;
}
@@ -1087,11 +1107,31 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
}
else if (params.getEvent() != null)
{
- auditQueryParams.addSearchKey(RM_AUDIT_DATA_EVENT_NAME, params.getEvent());
+ if (params.getEvent().equalsIgnoreCase(RM_AUDIT_EVENT_LOGIN_SUCCESS))
+ {
+ auditQueryParams.addSearchKey(RM_AUDIT_DATA_LOGIN_FULLNAME, null);
+ }
+ else if (params.getEvent().equalsIgnoreCase(RM_AUDIT_EVENT_LOGIN_FAILURE))
+ {
+ auditQueryParams.addSearchKey(RM_AUDIT_DATA_LOGIN_ERROR, null);
+ }
+ else
+ {
+ auditQueryParams.addSearchKey(RM_AUDIT_DATA_EVENT_NAME, params.getEvent());
+ }
}
// Get audit entries
- auditService.auditQuery(callback, dod5015AuditQueryParams, maxEntries);
+ SiteInfo siteInfo = siteService.getSite(DEFAULT_SITE_NAME);
+ if (siteInfo != null)
+ {
+ QName siteType = nodeService.getType(siteInfo.getNodeRef());
+ if (siteType.equals(TYPE_DOD_5015_SITE))
+ {
+ auditService.auditQuery(callback, dod5015AuditQueryParams, maxEntries);
+ }
+ }
+ // We always need to make the standard query - regardless of the type of RM site (to get events like RM site created).
auditService.auditQuery(callback, auditQueryParams, maxEntries);
// finish off the audit trail report
@@ -1114,7 +1154,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
* @param date The date for which the start should be calculated.
* @return Returns the start of the given date.
*/
- private Date getStartOfDay(Date date)
+ protected Date getStartOfDay(Date date)
{
return DateUtils.truncate(date == null ? new Date() : date, Calendar.DATE);
}
@@ -1479,22 +1519,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
json.put("fullName", entry.getFullName() == null ? "": entry.getFullName());
json.put("nodeRef", entry.getNodeRef() == null ? "": entry.getNodeRef());
- // TODO: Find another way for checking the event
- if (entry.getEvent().equals("Create Person") && entry.getNodeRef() != null)
- {
- NodeRef nodeRef = entry.getNodeRef();
- String userName = null;
- if(nodeService.exists(nodeRef))
- {
- userName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
- }
- json.put("nodeName", userName == null ? "": userName);
- json.put("createPerson", true);
- }
- else
- {
- json.put("nodeName", entry.getNodeName() == null ? "": entry.getNodeName());
- }
+ setNodeName(entry, json);
// TODO: Find another way for checking the event
if (entry.getEvent().equals("Delete RM Object"))
@@ -1544,7 +1569,6 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
}
json.put("changedValues", changedValues);
-
writer.write(json.toString());
}
catch (JSONException je)
@@ -1554,6 +1578,81 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
}
}
+ /**
+ * Update a JSON object with a node name for an audit event.
+ *
+ * @param entry The audit event.
+ * @param json The object to update.
+ * @throws JSONException If there is a problem updating the JSON.
+ */
+ private void setNodeName(RecordsManagementAuditEntry entry, JSONObject json) throws JSONException
+ {
+ String nodeName = null;
+ if (entry.getNodeRef() != null)
+ {
+ // TODO: Find another way for checking the event
+ switch (entry.getEvent())
+ {
+ case "Create Person":
+ nodeName = getNodeName(entry.getAfterProperties(), PROP_USERNAME);
+ // This is needed as older audit events (pre-2.7) were created without PROP_USERNAME being set.
+ NodeRef nodeRef = entry.getNodeRef();
+ if (nodeName == null && nodeService.exists(nodeRef))
+ {
+ nodeName = (String) nodeService.getProperty(nodeRef, PROP_USERNAME);
+ }
+ json.put("createPerson", true);
+ break;
+
+ case "Delete Person":
+ nodeName = getNodeName(entry.getBeforeProperties(), PROP_USERNAME);
+ json.put("deletePerson", true);
+ break;
+
+ case "Create User Group":
+ nodeName = getNodeName(entry.getAfterProperties(), PROP_AUTHORITY_DISPLAY_NAME, PROP_AUTHORITY_NAME);
+ break;
+
+ case "Delete User Group":
+ nodeName = getNodeName(entry.getBeforeProperties(), PROP_AUTHORITY_DISPLAY_NAME, PROP_AUTHORITY_NAME);
+ break;
+
+ case "Add To User Group":
+ nodeName = getNodeName(entry.getAfterProperties(), PARENT_GROUP);
+ break;
+
+ case "Remove From User Group":
+ nodeName = getNodeName(entry.getBeforeProperties(), PARENT_GROUP);
+ break;
+
+ default:
+ nodeName = entry.getNodeName();
+ break;
+ }
+ }
+ json.put("nodeName", nodeName == null ? "" : nodeName);
+ }
+
+ /**
+ * Get a node name using the first non-blank value from a properties object using a list of property names.
+ *
+ * @param properties The properties object.
+ * @param propertyNames The names of the properties to use. Return the first value that is not empty.
+ * @return The value of the property, or null if it's not there.
+ */
+ private String getNodeName(Map properties, QName... propertyNames)
+ {
+ for (QName propertyName : propertyNames)
+ {
+ String nodeName = (properties != null ? (String) properties.get(propertyName) : null);
+ if (!isBlank(nodeName))
+ {
+ return nodeName;
+ }
+ }
+ return null;
+ }
+
/**
* Helper method to convert value to MLText
*
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/AddToUserGroupAuditEvent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/AddToUserGroupAuditEvent.java
new file mode 100644
index 0000000000..79f46cf913
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/AddToUserGroupAuditEvent.java
@@ -0,0 +1,74 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.audit.event;
+
+import static org.alfresco.module.org_alfresco_module_rm.audit.event.UserGroupMembershipUtils.makePropertiesMap;
+import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.EVERY_EVENT;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.alfresco.repo.node.NodeServicePolicies.OnCreateChildAssociationPolicy;
+import org.alfresco.repo.policy.annotation.Behaviour;
+import org.alfresco.repo.policy.annotation.BehaviourBean;
+import org.alfresco.repo.policy.annotation.BehaviourKind;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Add an authority to a user group.
+ *
+ * @author Tom Page
+ * @since 2.7
+ */
+@BehaviourBean(defaultType = "cm:authorityContainer")
+public class AddToUserGroupAuditEvent extends AuditEvent implements OnCreateChildAssociationPolicy
+{
+ /** Node Service */
+ private NodeService nodeService;
+
+ /**
+ * Sets the node service
+ *
+ * @param nodeService nodeService to set
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /** Behaviour to audit adding an authority to a user group. */
+ @Override
+ @Behaviour(kind = BehaviourKind.ASSOCIATION, notificationFrequency = EVERY_EVENT, assocType = "cm:member")
+ public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNewNode)
+ {
+ Map auditProperties = makePropertiesMap(childAssocRef, nodeService);
+ recordsManagementAuditService.auditEvent(childAssocRef.getChildRef(), getName(), null, auditProperties, true);
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/CreatePersonAuditEvent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/CreatePersonAuditEvent.java
index 8c6e3dd6e1..b25404ab37 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/CreatePersonAuditEvent.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/CreatePersonAuditEvent.java
@@ -27,11 +27,18 @@
package org.alfresco.module.org_alfresco_module_rm.audit.event;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
/**
* Audits person creation.
@@ -42,17 +49,30 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
@BehaviourBean
public class CreatePersonAuditEvent extends AuditEvent implements OnCreateNodePolicy
{
+ /** Node Service */
+ private NodeService nodeService;
+
+ /**
+ * Sets the node service
+ *
+ * @param nodeService nodeService to set
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
/**
* @see org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy#onCreateNode(org.alfresco.service.cmr.repository.ChildAssociationRef)
*/
@Override
- @Behaviour
- (
- kind = BehaviourKind.CLASS,
- type = "cm:person"
- )
+ @Behaviour(kind = BehaviourKind.CLASS, type = "cm:person")
public void onCreateNode(ChildAssociationRef childAssocRef)
{
- recordsManagementAuditService.auditEvent(childAssocRef.getChildRef(), getName());
+ Map auditProperties = new HashMap<>();
+ auditProperties.put(ContentModel.PROP_USERNAME,
+ nodeService.getProperty(childAssocRef.getChildRef(), ContentModel.PROP_USERNAME));
+
+ recordsManagementAuditService.auditEvent(childAssocRef.getChildRef(), getName(), null, auditProperties);
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/CreateUserGroupAuditEvent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/CreateUserGroupAuditEvent.java
new file mode 100644
index 0000000000..24ebf27420
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/CreateUserGroupAuditEvent.java
@@ -0,0 +1,75 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.audit.event;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy;
+import org.alfresco.repo.policy.annotation.Behaviour;
+import org.alfresco.repo.policy.annotation.BehaviourBean;
+import org.alfresco.repo.policy.annotation.BehaviourKind;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Audits user group creation.
+ *
+ * @author Tom Page
+ * @since 2.7
+ */
+@BehaviourBean
+public class CreateUserGroupAuditEvent extends AuditEvent implements OnCreateNodePolicy
+{
+ /** Node Service */
+ private NodeService nodeService;
+
+ /**
+ * Sets the node service
+ *
+ * @param nodeService nodeService to set
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /** Behaviour to audit user group creation. */
+ @Override
+ @Behaviour(kind = BehaviourKind.CLASS, type = "cm:authorityContainer")
+ public void onCreateNode(ChildAssociationRef childAssocRef)
+ {
+ Map auditProperties = new HashMap<>();
+ auditProperties.put(ContentModel.PROP_AUTHORITY_DISPLAY_NAME,
+ nodeService.getProperty(childAssocRef.getChildRef(), ContentModel.PROP_AUTHORITY_DISPLAY_NAME));
+
+ recordsManagementAuditService.auditEvent(childAssocRef.getChildRef(), getName(), null, auditProperties);
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/DeletePersonAuditEvent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/DeletePersonAuditEvent.java
new file mode 100644
index 0000000000..a3aeab1e96
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/DeletePersonAuditEvent.java
@@ -0,0 +1,88 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.audit.event;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
+import org.alfresco.repo.policy.annotation.Behaviour;
+import org.alfresco.repo.policy.annotation.BehaviourBean;
+import org.alfresco.repo.policy.annotation.BehaviourKind;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Audits person deletion.
+ *
+ * @author Rodica Sutu
+ * @since 2.7
+ */
+@BehaviourBean
+public class DeletePersonAuditEvent extends AuditEvent implements BeforeDeleteNodePolicy
+{
+ /** Node Service*/
+ private NodeService nodeService;
+
+ /**
+ * Sets the node service
+ *
+ * @param nodeService nodeService to set
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Behaviour that will audit user deletion
+ *
+ * @param nodeRef the node to be deleted
+ *
+ */
+
+ @Override
+ @Behaviour
+ (
+ kind = BehaviourKind.CLASS,
+ type = "cm:person"
+ )
+ public void beforeDeleteNode(NodeRef nodeRef)
+ {
+ //retrieve the username property to be audited
+ Map userName = new HashMap<>();
+ userName.put(ContentModel.PROP_USERNAME, nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME));
+
+ //audit the property values before the delete event
+ recordsManagementAuditService.auditEvent(nodeRef, getName(), userName, null, true, false);
+ }
+
+
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/DeleteUserGroupAuditEvent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/DeleteUserGroupAuditEvent.java
new file mode 100644
index 0000000000..392b7e50f2
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/DeleteUserGroupAuditEvent.java
@@ -0,0 +1,82 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.audit.event;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
+import org.alfresco.repo.policy.annotation.Behaviour;
+import org.alfresco.repo.policy.annotation.BehaviourBean;
+import org.alfresco.repo.policy.annotation.BehaviourKind;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Audits user group deletion.
+ *
+ * @author Tom Page
+ * @since 2.7
+ */
+@BehaviourBean
+public class DeleteUserGroupAuditEvent extends AuditEvent implements BeforeDeleteNodePolicy
+{
+ /** Node Service */
+ private NodeService nodeService;
+
+ /**
+ * Sets the node service
+ *
+ * @param nodeService nodeService to set
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Behaviour that will audit user group deletion
+ *
+ * @param nodeRef the node to be deleted
+ */
+ @Override
+ @Behaviour(kind = BehaviourKind.CLASS, type = "cm:authorityContainer")
+ public void beforeDeleteNode(NodeRef nodeRef)
+ {
+ // Retrieve the authority name property to be audited
+ Map auditProperties = new HashMap<>();
+ auditProperties.put(ContentModel.PROP_AUTHORITY_DISPLAY_NAME,
+ nodeService.getProperty(nodeRef, ContentModel.PROP_AUTHORITY_DISPLAY_NAME));
+
+ //audit the property values before the delete event
+ recordsManagementAuditService.auditEvent(nodeRef, getName(), auditProperties, null, true, false);
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/RemoveFromUserGroupAuditEvent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/RemoveFromUserGroupAuditEvent.java
new file mode 100644
index 0000000000..952a1d09cb
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/RemoveFromUserGroupAuditEvent.java
@@ -0,0 +1,74 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.audit.event;
+
+import static org.alfresco.module.org_alfresco_module_rm.audit.event.UserGroupMembershipUtils.makePropertiesMap;
+import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.EVERY_EVENT;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import org.alfresco.repo.node.NodeServicePolicies.OnDeleteChildAssociationPolicy;
+import org.alfresco.repo.policy.annotation.Behaviour;
+import org.alfresco.repo.policy.annotation.BehaviourBean;
+import org.alfresco.repo.policy.annotation.BehaviourKind;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Remove an authority from a user group.
+ *
+ * @author Tom Page
+ * @since 2.7
+ */
+@BehaviourBean(defaultType = "cm:authorityContainer")
+public class RemoveFromUserGroupAuditEvent extends AuditEvent implements OnDeleteChildAssociationPolicy
+{
+ /** Node Service */
+ private NodeService nodeService;
+
+ /**
+ * Sets the node service
+ *
+ * @param nodeService nodeService to set
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /** Behaviour to audit removing an authority from a user group. */
+ @Override
+ @Behaviour(kind = BehaviourKind.ASSOCIATION, notificationFrequency = EVERY_EVENT, assocType = "cm:member")
+ public void onDeleteChildAssociation(ChildAssociationRef childAssocRef)
+ {
+ Map auditProperties = makePropertiesMap(childAssocRef, nodeService);
+ recordsManagementAuditService.auditEvent(childAssocRef.getChildRef(), getName(), auditProperties, null, true);
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/UserGroupMembershipUtils.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/UserGroupMembershipUtils.java
new file mode 100644
index 0000000000..15fa678b9a
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/audit/event/UserGroupMembershipUtils.java
@@ -0,0 +1,92 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.audit.event;
+
+import static org.apache.commons.lang3.StringUtils.isBlank;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Utility class for creating audit events about user group membership.
+ *
+ * @author Tom Page
+ * @since 2.7
+ */
+public class UserGroupMembershipUtils
+{
+ /** A QName to display for the parent group's name. */
+ public static final QName PARENT_GROUP = QName.createQName(RecordsManagementModel.RM_URI, "Parent Group");
+ /** A QName to display for a child group's name. */
+ private static final QName CHILD_GROUP = QName.createQName(RecordsManagementModel.RM_URI, "Child Group");
+
+ /**
+ * Create a properties map from the given cm:member association.
+ *
+ * @param childAssocRef The association to use.
+ * @param nodeService The node service.
+ * @return A map containing the names of the parent and child.
+ */
+ public static Map makePropertiesMap(ChildAssociationRef childAssocRef, NodeService nodeService)
+ {
+ Map auditProperties = new HashMap<>();
+ // Set exactly one of the child group property or the child user name property.
+ String childGroupName = getUserGroupName(childAssocRef.getChildRef(), nodeService);
+ if (!isBlank(childGroupName))
+ {
+ auditProperties.put(CHILD_GROUP, childGroupName);
+ }
+ String childUserName = (String) nodeService.getProperty(childAssocRef.getChildRef(), ContentModel.PROP_USERNAME);
+ if (!isBlank(childUserName))
+ {
+ auditProperties.put(ContentModel.PROP_USERNAME, childUserName);
+ }
+ // Set the parent group name.
+ auditProperties.put(PARENT_GROUP, getUserGroupName(childAssocRef.getParentRef(), nodeService));
+ return auditProperties;
+ }
+
+ /** Get a name that can be displayed for the user group. */
+ private static String getUserGroupName(NodeRef nodeRef, NodeService nodeService)
+ {
+ String groupName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_AUTHORITY_DISPLAY_NAME);
+ if (isBlank(groupName))
+ {
+ groupName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_AUTHORITY_NAME);
+ }
+ return groupName;
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityService.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityService.java
index 27dedaef46..aa25dac7f3 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityService.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityService.java
@@ -151,4 +151,12 @@ public interface CapabilityService
* @param group The group which should be removed
*/
void removeGroup(Group group);
+
+ /**
+ * Check if the current user has the given capability.
+ *
+ * @param capabilityName
+ * @return
+ */
+ boolean hasCapability(NodeRef nodeRef, String capabilityName);
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityServiceImpl.java
index ae8ae6ff34..0d130d8a55 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/CapabilityServiceImpl.java
@@ -282,4 +282,24 @@ public class CapabilityServiceImpl implements CapabilityService
groups.remove(group.getId());
}
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService#hasCapability(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
+ */
+ @Override
+ public boolean hasCapability(NodeRef nodeRef, String capabilityName)
+ {
+ Capability capability = getCapability(capabilityName);
+ if (capability != null)
+ {
+ AccessStatus accessStatus = getCapabilityAccessState(nodeRef, capabilityName);
+
+ if (accessStatus.equals(AccessStatus.ALLOWED))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java
index e929879a32..264915f9c6 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java
@@ -37,6 +37,13 @@ import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
+import net.sf.acegisecurity.AccessDeniedException;
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.ConfigAttribute;
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.afterinvocation.AfterInvocationProvider;
+import net.sf.acegisecurity.vote.AccessDecisionVoter;
+
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.repo.search.SimpleResultSetMetaData;
@@ -62,13 +69,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
-import net.sf.acegisecurity.AccessDeniedException;
-import net.sf.acegisecurity.Authentication;
-import net.sf.acegisecurity.ConfigAttribute;
-import net.sf.acegisecurity.ConfigAttributeDefinition;
-import net.sf.acegisecurity.afterinvocation.AfterInvocationProvider;
-import net.sf.acegisecurity.vote.AccessDecisionVoter;
-
/**
* RM After Invocation Provider
*/
@@ -285,11 +285,8 @@ public class RMAfterInvocationProvider extends RMSecurityCommon
{
for (ConfigAttributeDefintion cad : supportedDefinitions)
{
- if (cad.parent && parentResult == AccessDecisionVoter.ACCESS_DENIED)
- {
- throw new AccessDeniedException("Access Denied");
- }
- else if (!cad.parent && childResult == AccessDecisionVoter.ACCESS_DENIED)
+ if ((cad.parent && parentResult == AccessDecisionVoter.ACCESS_DENIED)
+ || (!cad.parent && childResult == AccessDecisionVoter.ACCESS_DENIED))
{
throw new AccessDeniedException("Access Denied");
}
@@ -358,11 +355,8 @@ public class RMAfterInvocationProvider extends RMSecurityCommon
continue;
}
- if (cad.parent && parentReadCheck != AccessDecisionVoter.ACCESS_GRANTED)
- {
- throw new AccessDeniedException("Access Denied");
- }
- else if (childReadCheck != AccessDecisionVoter.ACCESS_GRANTED)
+ if ((cad.parent && parentReadCheck != AccessDecisionVoter.ACCESS_GRANTED)
+ || (childReadCheck != AccessDecisionVoter.ACCESS_GRANTED))
{
throw new AccessDeniedException("Access Denied");
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/MayBeScheduledCapabilityCondition.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/MayBeScheduledCapabilityCondition.java
index 91c0802be9..894b618119 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/MayBeScheduledCapabilityCondition.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/capability/declarative/condition/MayBeScheduledCapabilityCondition.java
@@ -94,17 +94,8 @@ public class MayBeScheduledCapabilityCondition extends AbstractCapabilityConditi
*/
private boolean checkDispositionLevel(NodeRef nodeRef, DispositionSchedule dispositionSchedule)
{
- boolean result = false;
boolean isRecordLevelDisposition = dispositionSchedule.isRecordLevelDisposition();
- if (recordService.isRecord(nodeRef) && isRecordLevelDisposition)
- {
- result = true;
- }
- else if (recordFolderService.isRecordFolder(nodeRef) && !isRecordLevelDisposition)
-
- {
- result = true;
- }
- return result;
+ return (recordService.isRecord(nodeRef) && isRecordLevelDisposition)
+ || (recordFolderService.isRecordFolder(nodeRef) && !isRecordLevelDisposition);
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/ContentDestructionComponent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/ContentDestructionComponent.java
index fb77f3efb6..b86b1b0c2a 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/ContentDestructionComponent.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/ContentDestructionComponent.java
@@ -33,6 +33,7 @@ import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.model.RenditionModel;
+import org.alfresco.module.org_alfresco_module_rm.util.ContentBinDuplicationUtility;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -63,6 +64,9 @@ public class ContentDestructionComponent
/** behaviour filter */
private BehaviourFilter behaviourFilter;
+ /** Utility class for duplicating content */
+ private ContentBinDuplicationUtility contentBinDuplicationUtility;
+
/** indicates whether cleansing is enabled or not */
private boolean cleansingEnabled = false;
@@ -138,6 +142,15 @@ public class ContentDestructionComponent
this.behaviourFilter = behaviourFilter;
}
+ /**
+ * Setter for content duplication utility class
+ * @param contentBinDuplicationUtility ContentBinDuplicationUtility
+ */
+ public void setContentBinDuplicationUtility(ContentBinDuplicationUtility contentBinDuplicationUtility)
+ {
+ this.contentBinDuplicationUtility = contentBinDuplicationUtility;
+ }
+
/**
* @param cleansingEnabled true if cleansing enabled, false otherwise
*/
@@ -214,16 +227,19 @@ public class ContentDestructionComponent
// get content data
ContentData dataContent = (ContentData)entry.getValue();
- // if enabled cleanse content
- if (isCleansingEnabled())
+ if (!contentBinDuplicationUtility.hasAtLeastOneOtherReference(nodeRef))
{
- // register for cleanse then immediate destruction
- getEagerContentStoreCleaner().registerOrphanedContentUrlForCleansing(dataContent.getContentUrl());
- }
- else
- {
- // register for immediate destruction
- getEagerContentStoreCleaner().registerOrphanedContentUrl(dataContent.getContentUrl(), true);
+ // if enabled cleanse content
+ if (isCleansingEnabled())
+ {
+ // register for cleanse then immediate destruction
+ getEagerContentStoreCleaner().registerOrphanedContentUrlForCleansing(dataContent.getContentUrl());
+ }
+ else
+ {
+ // register for immediate destruction
+ getEagerContentStoreCleaner().registerOrphanedContentUrl(dataContent.getContentUrl(), true);
+ }
}
// clear the property
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/cleanser/ContentCleanser.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/cleanser/ContentCleanser.java
index 587b5b8534..fc79ab3d23 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/cleanser/ContentCleanser.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/content/cleanser/ContentCleanser.java
@@ -34,6 +34,8 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
+import org.alfresco.error.AlfrescoRuntimeException;
+
/**
* Content cleanser base implementation.
*
@@ -41,22 +43,22 @@ import java.util.Random;
* @since 2.4.a
*/
public abstract class ContentCleanser
-{
+{
/**
* Cleanse file
*
* @param file file to cleanse
*/
public abstract void cleanse(File file);
-
+
/**
* Overwrite files bytes with provided overwrite operation
*
- * @param file file
+ * @param file file
* @param overwriteOperation overwrite operation
*/
protected void overwrite(File file, OverwriteOperation overwriteOperation)
- {
+ {
// get the number of bytes
long bytes = file.length();
try
@@ -74,18 +76,18 @@ public abstract class ContentCleanser
catch (IOException ioException)
{
// re-throw
- throw new RuntimeException("Unable to overwrite file", ioException);
+ throw new AlfrescoRuntimeException("Unable to overwrite file", ioException);
}
}
-
+
/**
- * Overwrite operation
+ * Overwrite operation
*/
protected abstract class OverwriteOperation
{
public abstract void operation(OutputStream os) throws IOException;
}
-
+
/**
* Overwrite with zeros operation
*/
@@ -96,7 +98,7 @@ public abstract class ContentCleanser
os.write(0);
}
};
-
+
/**
* Overwrite with ones operation
*/
@@ -107,14 +109,14 @@ public abstract class ContentCleanser
os.write(0xff);
}
};
-
+
/**
* Overwrite with random operation
*/
protected OverwriteOperation overwriteRandom = new OverwriteOperation()
{
private Random random = new Random();
-
+
public void operation(OutputStream os) throws IOException
{
byte[] randomByte = new byte[1];
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/dataset/DataSetServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/dataset/DataSetServiceImpl.java
index 6717718bc5..d12e072d5e 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/dataset/DataSetServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/dataset/DataSetServiceImpl.java
@@ -291,7 +291,7 @@ public class DataSetServiceImpl implements DataSetService, RecordsManagementMode
}
catch (Exception ex)
{
- throw new RuntimeException("Unexpected exception thrown. Please refer to the log files for details.", ex);
+ throw new AlfrescoRuntimeException("Unexpected exception thrown. Please refer to the log files for details.", ex);
}
finally
{
@@ -304,7 +304,7 @@ public class DataSetServiceImpl implements DataSetService, RecordsManagementMode
}
catch (IOException ex)
{
- throw new RuntimeException("Failed to close the input stream!", ex);
+ throw new AlfrescoRuntimeException("Failed to close the input stream!", ex);
}
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionActionImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionActionImpl.java
index 3d5b7e7700..31f0f88d4d 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionActionImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionActionImpl.java
@@ -35,11 +35,13 @@ import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry;
import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction;
import org.alfresco.module.org_alfresco_module_rm.event.EventCompletionDetails;
import org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEvent;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.module.org_alfresco_module_rm.script.slingshot.RMSearchGet;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
@@ -328,6 +330,12 @@ public class DispositionActionImpl implements DispositionAction,
props.put(PROP_EVENT_EXECUTION_COMPLETED_BY, completedByValue);
services.getNodeService().setProperties(eventNodeRef, props);
+ // check a specific event from rmEventConfigBootstrap.json
+ if (eventName.equals("declassification_review"))
+ {
+ setDeclassificationReview(eventNodeRef, completedAtValue, completedByValue);
+ }
+
// Check to see if the events eligible property needs to be updated
updateEventEligible();
@@ -518,4 +526,38 @@ public class DispositionActionImpl implements DispositionAction,
return eligible;
}
+
+ /**
+ * Sets declassification review authority and date on records and record folder
+ *
+ * @param eventNodeRef Declassification review event node ref
+ * @param completedAtValue Declassification review authority
+ * @param completedByValue Declassification review date
+ */
+ private void setDeclassificationReview(NodeRef eventNodeRef, Date completedAtValue, String completedByValue)
+ {
+ NodeRef nextDispositionActionNodeRef = services.getNodeService().getPrimaryParent(eventNodeRef).getParentRef();
+ NodeRef nodeRef = services.getNodeService().getPrimaryParent(nextDispositionActionNodeRef).getParentRef();
+ setPropsOnContent(nodeRef, completedAtValue, completedByValue);
+
+ // check if the node is a record folder then set the declassification review on the records also
+ if (services.getNodeService().getType(nodeRef).equals(RecordsManagementModel.TYPE_RECORD_FOLDER))
+ {
+ // get all the records inside the record folder
+ List records = services.getNodeService().getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ for (ChildAssociationRef child : records)
+ {
+ NodeRef recordNodeRef = child.getChildRef();
+ setPropsOnContent(recordNodeRef, completedAtValue, completedByValue);
+ }
+ }
+ }
+
+ private void setPropsOnContent(NodeRef nodeRef, Date completedAtValue, String completedByValue)
+ {
+ Map nodeProps = services.getNodeService().getProperties(nodeRef);
+ nodeProps.put(PROP_RS_DECLASSIFICATION_REVIEW_COMPLETED_AT, completedAtValue);
+ nodeProps.put(PROP_RS_DECLASSIFICATION_REVIEW_COMPLETED_BY, completedByValue);
+ services.getNodeService().setProperties(nodeRef, nodeProps);
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java
index dccc56df6b..1f221f9436 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java
@@ -268,11 +268,9 @@ public interface DispositionService
*
* @param nodeRef The node which the schedule applies to.
* @param dispositionActionDefinition The definition of the disposition action.
- * @param allowContextFromAsOf true if the context date is allowed to be obtained from the disposition "as of" property.
* @return The new "disposition as of" date.
*/
- Date calculateAsOfDate(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition,
- boolean allowContextFromAsOf);
+ Date calculateAsOfDate(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition);
/**
* Gets the origin disposition schedule for the record, not the calculated one
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java
index e044026c75..6c74379f8c 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java
@@ -132,7 +132,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
/**
* Set the dictionary service
*
- * @param dictionaryServic the dictionary service
+ * @param dictionaryService the dictionary service
*/
@Override
public void setDictionaryService(DictionaryService dictionaryService)
@@ -231,7 +231,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
DispositionActionDefinition nextDispositionActionDefinition = dispositionActionDefinitions.get(0);
// initialise the details of the next disposition action
- initialiseDispositionAction(nodeRef, nextDispositionActionDefinition, true);
+ initialiseDispositionAction(nodeRef, nextDispositionActionDefinition);
}
}
}
@@ -436,7 +436,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
if (this.nodeService.hasAspect(nodeRef, ASPECT_SCHEDULED))
{
List childAssocs = this.nodeService.getChildAssocs(nodeRef, ASSOC_DISPOSITION_SCHEDULE, RegexQNamePattern.MATCH_ALL);
- if (childAssocs.size() != 0)
+ if (!childAssocs.isEmpty())
{
ChildAssociationRef firstChildAssocRef = childAssocs.get(0);
result = firstChildAssocRef.getChildRef();
@@ -459,7 +459,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
if (nodeService.exists(dsNodeRef))
{
List assocs = this.nodeService.getParentAssocs(dsNodeRef, ASSOC_DISPOSITION_SCHEDULE, RegexQNamePattern.MATCH_ALL);
- if (assocs.size() != 0)
+ if (!assocs.isEmpty())
{
if (assocs.size() != 1)
{
@@ -519,7 +519,6 @@ public class DispositionServiceImpl extends ServiceBaseImpl
*
* @param isRecordLevelDisposition
* @param rmContainer
- * @param root
* @return
*/
private List getDisposableItemsImpl(boolean isRecordLevelDisposition, NodeRef rmContainer)
@@ -583,13 +582,13 @@ public class DispositionServiceImpl extends ServiceBaseImpl
// Check whether there is already a disposition schedule object present
List assocs = nodeService.getChildAssocs(nodeRef, ASSOC_DISPOSITION_SCHEDULE, RegexQNamePattern.MATCH_ALL);
- if (assocs.size() == 0)
+ if (assocs.isEmpty())
{
DispositionSchedule currentDispositionSchdule = getDispositionSchedule(nodeRef);
if (currentDispositionSchdule != null)
{
List items = getDisposableItemsImpl(currentDispositionSchdule.isRecordLevelDisposition(), nodeRef);
- if (items.size() != 0)
+ if (!items.isEmpty())
{
throw new AlfrescoRuntimeException("Can not create a retention schedule if there are disposable items already under the control of an other retention schedule");
}
@@ -671,7 +670,6 @@ public class DispositionServiceImpl extends ServiceBaseImpl
* Updates the given disposition action definition belonging to the given disposition
* schedule.
*
- * @param schedule The DispositionSchedule the action belongs to
* @param actionDefinition The DispositionActionDefinition to update
* @param actionDefinitionParams Map of parameters to use to update the action definition
* @return The updated DispositionActionDefinition
@@ -698,12 +696,11 @@ public class DispositionServiceImpl extends ServiceBaseImpl
*
* @param nodeRef node reference
* @param dispositionActionDefinition disposition action definition
- * @param allowContextFromAsOf true if the context date is allowed to be obtained from the disposition "as of" property.
*/
- private DispositionAction initialiseDispositionAction(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition, boolean allowContextFromAsOf)
+ private DispositionAction initialiseDispositionAction(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition)
{
List childAssocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, ASSOC_NEXT_DISPOSITION_ACTION, 1, true);
- if (childAssocs != null && childAssocs.size() > 0)
+ if (childAssocs != null && !childAssocs.isEmpty())
{
return new DispositionActionImpl(serviceRegistry, childAssocs.get(0).getChildRef());
}
@@ -711,7 +708,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
// Create the properties
Map props = new HashMap(10);
- Date asOfDate = calculateAsOfDate(nodeRef, dispositionActionDefinition, allowContextFromAsOf);
+ Date asOfDate = calculateAsOfDate(nodeRef, dispositionActionDefinition);
// Set the property values
props.put(PROP_DISPOSITION_ACTION_ID, dispositionActionDefinition.getId());
@@ -745,12 +742,10 @@ public class DispositionServiceImpl extends ServiceBaseImpl
*
* @param nodeRef The node which the schedule applies to.
* @param dispositionActionDefinition The definition of the disposition action.
- * @param allowContextFromAsOf true if the context date is allowed to be obtained from the disposition "as of" property.
* @return The new "disposition as of" date.
*/
@Override
- public Date calculateAsOfDate(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition,
- boolean allowContextFromAsOf)
+ public Date calculateAsOfDate(NodeRef nodeRef, DispositionActionDefinition dispositionActionDefinition)
{
// Calculate the asOf date
Date asOfDate = null;
@@ -761,12 +756,27 @@ public class DispositionServiceImpl extends ServiceBaseImpl
// Get the period properties value
QName periodProperty = dispositionActionDefinition.getPeriodProperty();
- if (periodProperty != null && (allowContextFromAsOf
- || !RecordsManagementModel.PROP_DISPOSITION_AS_OF.equals(periodProperty)))
+ if (periodProperty != null)
{
- // doesn't matter if the period property isn't set ... the asOfDate will get updated later
- // when the value of the period property is set
- contextDate = (Date)this.nodeService.getProperty(nodeRef, periodProperty);
+ if (RecordsManagementModel.PROP_DISPOSITION_AS_OF.equals(periodProperty))
+ {
+ DispositionAction lastCompletedDispositionAction = getLastCompletedDispostionAction(nodeRef);
+ if (lastCompletedDispositionAction != null)
+ {
+ contextDate = lastCompletedDispositionAction.getCompletedAt();
+ }
+ else
+ {
+ contextDate = (Date)this.nodeService.getProperty(nodeRef, periodProperty);
+ }
+
+ }
+ else
+ {
+ // doesn't matter if the period property isn't set ... the asOfDate will get updated later
+ // when the value of the period property is set
+ contextDate = (Date)this.nodeService.getProperty(nodeRef, periodProperty);
+ }
}
else
{
@@ -798,63 +808,77 @@ public class DispositionServiceImpl extends ServiceBaseImpl
public boolean isNextDispositionActionEligible(NodeRef nodeRef)
{
boolean result = false;
-
// Get the disposition instructions
DispositionSchedule di = getDispositionSchedule(nodeRef);
- NodeRef nextDa = getNextDispositionActionNodeRef(nodeRef);
+ DispositionAction nextDa = getNextDispositionAction(nodeRef);
if (di != null &&
this.nodeService.hasAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE) &&
nextDa != null)
{
- // If it has an asOf date and it is greater than now the action is eligible
- Date asOf = (Date)this.nodeService.getProperty(nextDa, PROP_DISPOSITION_AS_OF);
- if (asOf != null &&
- asOf.before(new Date()))
+ // for accession step we can have also AND between step conditions
+ Boolean combineSteps = false;
+ if (nextDa.getName().equals("accession"))
{
- result = true;
- }
-
- if (!result)
- {
- DispositionAction da = new DispositionActionImpl(serviceRegistry, nextDa);
- DispositionActionDefinition dad = da.getDispositionActionDefinition();
- if (dad != null)
- {
- boolean firstComplete = dad.eligibleOnFirstCompleteEvent();
-
- List assocs = this.nodeService.getChildAssocs(nextDa, ASSOC_EVENT_EXECUTIONS, RegexQNamePattern.MATCH_ALL);
- for (ChildAssociationRef assoc : assocs)
+ NodeRef accessionNodeRef = di.getDispositionActionDefinitionByName("accession").getNodeRef();
+ if (accessionNodeRef != null) {
+ Boolean combineStepsProp = (Boolean)this.nodeService.getProperty(accessionNodeRef, PROP_COMBINE_DISPOSITION_STEP_CONDITIONS);
+ if (combineStepsProp != null)
{
- NodeRef eventExecution = assoc.getChildRef();
- Boolean isCompleteValue = (Boolean)this.nodeService.getProperty(eventExecution, PROP_EVENT_EXECUTION_COMPLETE);
- boolean isComplete = false;
- if (isCompleteValue != null)
- {
- isComplete = isCompleteValue.booleanValue();
+ combineSteps = combineStepsProp;
+ }
+ }
+ }
+ Date asOf = (Date)this.nodeService.getProperty(nextDa.getNodeRef(), PROP_DISPOSITION_AS_OF);
+ Boolean asOfDateInPast = false;
+ if (asOf != null)
+ {
+ asOfDateInPast = asOf.before(new Date());
+ }
+ if (asOfDateInPast && !combineSteps)
+ {
+ return true;
+ }
+ else if(!asOfDateInPast && combineSteps)
+ {
+ return false;
+ }
+ DispositionAction da = new DispositionActionImpl(serviceRegistry, nextDa.getNodeRef());
+ DispositionActionDefinition dad = da.getDispositionActionDefinition();
+ if (dad != null)
+ {
+ boolean firstComplete = dad.eligibleOnFirstCompleteEvent();
- // implement AND and OR combination of event completions
- if (isComplete)
+ List assocs = this.nodeService.getChildAssocs(nextDa.getNodeRef(), ASSOC_EVENT_EXECUTIONS, RegexQNamePattern.MATCH_ALL);
+ for (ChildAssociationRef assoc : assocs)
+ {
+ NodeRef eventExecution = assoc.getChildRef();
+ Boolean isCompleteValue = (Boolean)this.nodeService.getProperty(eventExecution, PROP_EVENT_EXECUTION_COMPLETE);
+ boolean isComplete = false;
+ if (isCompleteValue != null)
+ {
+ isComplete = isCompleteValue.booleanValue();
+
+ // implement AND and OR combination of event completions
+ if (isComplete)
+ {
+ result = true;
+ if (firstComplete)
{
- result = true;
- if (firstComplete)
- {
- break;
- }
+ break;
}
- else
+ }
+ else
+ {
+ result = false;
+ if (!firstComplete)
{
- result = false;
- if (!firstComplete)
- {
- break;
- }
+ break;
}
}
}
}
}
}
-
return result;
}
@@ -868,7 +892,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
{
NodeRef result = null;
List assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, ASSOC_NEXT_DISPOSITION_ACTION, 1, true);
- if (assocs.size() != 0)
+ if (!assocs.isEmpty())
{
result = assocs.get(0).getChildRef();
}
@@ -989,7 +1013,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
if (nodeService.hasAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE))
{
List assocs = nodeService.getChildAssocs(nodeRef, ASSOC_NEXT_DISPOSITION_ACTION, ASSOC_NEXT_DISPOSITION_ACTION);
- if (assocs.size() > 0)
+ if (!assocs.isEmpty())
{
currentDispositionAction = assocs.get(0).getChildRef();
}
@@ -1044,7 +1068,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl
nodeService.addAspect(nodeRef, ASPECT_DISPOSITION_LIFECYCLE, null);
}
- initialiseDispositionAction(nodeRef, nextDispositionActionDefinition, false);
+ initialiseDispositionAction(nodeRef, nextDispositionActionDefinition);
}
}
@@ -1117,14 +1141,14 @@ public class DispositionServiceImpl extends ServiceBaseImpl
{
DispositionSchedule ds = new DispositionScheduleImpl(serviceRegistry, nodeService, dispositionSchedule);
List assocs = nodeService.getChildAssocs(dispositionSchedule);
- if (assocs != null && assocs.size() > 0)
+ if (assocs != null && !assocs.isEmpty())
{
for (ChildAssociationRef assoc : assocs)
{
if (assoc != null && assoc.getQName().getLocalName().contains(dispositionActionName))
{
DispositionActionDefinition actionDefinition = ds.getDispositionActionDefinition(assoc.getChildRef().getId());
- return calculateAsOfDate(record, actionDefinition, true);
+ return calculateAsOfDate(record, actionDefinition);
}
}
}
@@ -1339,14 +1363,14 @@ public class DispositionServiceImpl extends ServiceBaseImpl
{
recordOrFolder = folder;
}
- DispositionAction firstDispositionAction = initialiseDispositionAction(recordOrFolder, firstDispositionActionDef, true);
+ DispositionAction firstDispositionAction = initialiseDispositionAction(recordOrFolder, firstDispositionActionDef);
newAction = firstDispositionAction.getNodeRef();
newDispositionActionName = (String)nodeService.getProperty(newAction, PROP_DISPOSITION_ACTION_NAME);
newDispositionActionDateAsOf = firstDispositionAction.getAsOfDate();
}
else if (firstDispositionActionDef.getPeriod() != null)
{
- Date firstActionDate = calculateAsOfDate(record, firstDispositionActionDef, true);
+ Date firstActionDate = calculateAsOfDate(record, firstDispositionActionDef);
if (firstActionDate == null || (newDispositionActionDateAsOf != null
&& newDispositionActionDateAsOf.before(firstActionDate)))
{
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java
index a315160fa5..152562712c 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/property/DispositionProperty.java
@@ -32,6 +32,7 @@ import static org.apache.commons.lang3.BooleanUtils.isNotTrue;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -258,25 +259,9 @@ public class DispositionProperty extends BaseBehaviourBean
*/
private boolean isPropertyUpdated(Map before, Map after)
{
- boolean result = false;
-
Serializable beforeValue = before.get(propertyName);
Serializable afterValue = after.get(propertyName);
- if (beforeValue == null && afterValue != null)
- {
- result = true;
- }
- else if (beforeValue != null && afterValue == null)
- {
- result = true;
- }
- else if (beforeValue != null && afterValue != null &&
- !beforeValue.equals(afterValue))
- {
- result = true;
- }
-
- return result;
+ return !Objects.equals(beforeValue, afterValue);
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/email/RFC822MetadataExtracter.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/email/RFC822MetadataExtracter.java
index 51839efb8d..ae6113deed 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/email/RFC822MetadataExtracter.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/email/RFC822MetadataExtracter.java
@@ -33,6 +33,7 @@ import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -69,7 +70,13 @@ public class RFC822MetadataExtracter extends org.alfresco.repo.content.metadata.
protected void filterSystemProperties(Map systemProperties, Map targetProperties)
{
NodeRef nodeRef = getNodeRef(targetProperties);
- if (nodeRef == null || !nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD))
+ if(nodeRef == null)
+ {
+ return;
+ }
+
+ // Remove record properties from non-record nodes
+ if (!nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD))
{
// Remove all rm namespace properties from the system map
Map clone = new HashMap(systemProperties);
@@ -81,6 +88,20 @@ public class RFC822MetadataExtracter extends org.alfresco.repo.content.metadata.
}
}
}
+
+ // Remove dod5015 properties from non-dod5015 nodes
+ if (!nodeService.hasAspect(nodeRef, DOD5015Model.ASPECT_DOD_5015_RECORD))
+ {
+ // Remove all dod5015 namespace properties from the system map
+ Map clone = new HashMap<>(systemProperties);
+ for (QName propName : clone.keySet())
+ {
+ if (DOD5015Model.DOD_URI.equals(propName.getNamespaceURI()))
+ {
+ systemProperties.remove(propName);
+ }
+ }
+ }
}
/**
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
index d20ca31db7..04ca0201a0 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java
@@ -28,6 +28,8 @@
package org.alfresco.module.org_alfresco_module_rm.jscript.app;
import static org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel.READ_RECORDS;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_COMBINE_DISPOSITION_STEP_CONDITIONS;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_DISPOSITION_EVENT_COMBINATION;
import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED;
import java.util.ArrayList;
@@ -38,6 +40,9 @@ import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.capability.impl.ViewRecordsCapability;
+import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction;
+import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
+import org.alfresco.module.org_alfresco_module_rm.event.EventCompletionDetails;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
@@ -99,6 +104,11 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS
/** site service */
private SiteService siteService;
+ /**
+ * Disposition service
+ */
+ private DispositionService dispositionService;
+
/** Indicators */
private List indicators = new ArrayList();
@@ -154,6 +164,22 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS
this.capabilityService = capabilityService;
}
+ /**
+ * @return the filePlanService
+ */
+ protected FilePlanService getFileplanService()
+ {
+ return this.filePlanService;
+ }
+
+ /**
+ * @return the capabilityService
+ */
+ protected CapabilityService getCapabilityService()
+ {
+ return this.capabilityService;
+ }
+
/**
* @param dictionaryService dictionary service
*/
@@ -214,6 +240,14 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS
this.jsonConversionComponentCache = jsonConversionComponentCache;
}
+ /**
+ * @param dispositionService the disposition service
+ */
+ public void setDispositionService(DispositionService dispositionService)
+ {
+ this.dispositionService = dispositionService;
+ }
+
/**
* The initialise method
*/
@@ -440,6 +474,23 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS
// Set the actions array
setActions(rmNodeValues, nodeRef);
+
+ //Add details of the next incomplete event in the disposition schedule
+ if(dispositionService.getNextDispositionAction(nodeRef) != null)
+ {
+ for(EventCompletionDetails details: dispositionService.getNextDispositionAction(nodeRef).getEventCompletionDetails())
+ {
+ if(!details.isEventComplete())
+ {
+ HashMap properties = ((HashMap) rmNodeValues.get("properties"));
+ properties.put("combineDispositionStepConditions", nodeService.getProperty(dispositionService.getNextDispositionAction(nodeRef).getDispositionActionDefinition().getNodeRef(), PROP_COMBINE_DISPOSITION_STEP_CONDITIONS));
+ properties.put("incompleteDispositionEvent", details.getEventName());
+ properties.put("dispositionEventCombination", nodeService.getProperty(dispositionService.getNextDispositionAction(nodeRef).getDispositionActionDefinition().getNodeRef(), PROP_DISPOSITION_EVENT_COMBINATION));
+ break;
+ }
+ }
+ }
+
return rmNodeValues;
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
index e1ac53d9a5..7e6fc45ca3 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java
@@ -99,6 +99,7 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
QName PROP_DISPOSITION_PERIOD_PROPERTY = QName.createQName(RM_URI, "dispositionPeriodProperty");
QName PROP_DISPOSITION_EVENT = QName.createQName(RM_URI, "dispositionEvent");
QName PROP_DISPOSITION_EVENT_COMBINATION = QName.createQName(RM_URI, "dispositionEventCombination");
+ QName PROP_COMBINE_DISPOSITION_STEP_CONDITIONS = QName.createQName(RM_URI, "combineDispositionStepConditions");
QName PROP_DISPOSITION_LOCATION = QName.createQName(RM_URI, "dispositionLocation");
QName PROP_DISPOSITION_ACTION_GHOST_ON_DESTROY = QName.createQName(RM_URI, "dispositionActionGhostOnDestroy");
@@ -246,6 +247,8 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
QName PROP_RS_HAS_DISPOITION_SCHEDULE = QName.createQName(RM_URI, "recordSearchHasDispositionSchedule");
QName PROP_RS_DISPOITION_INSTRUCTIONS = QName.createQName(RM_URI, "recordSearchDispositionInstructions");
QName PROP_RS_DISPOITION_AUTHORITY = QName.createQName(RM_URI, "recordSearchDispositionAuthority");
+ QName PROP_RS_DECLASSIFICATION_REVIEW_COMPLETED_AT = QName.createQName(RM_URI, "declassificationReviewCompletedAt");
+ QName PROP_RS_DECLASSIFICATION_REVIEW_COMPLETED_BY = QName.createQName(RM_URI, "declassificationReviewCompletedBy");
/** @depreacted as of 2.2, because disposable items can now be in multiple holds */
@Deprecated
QName PROP_RS_HOLD_REASON = QName.createQName(RM_URI, "recordSearchHoldReason");
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
index 441af631bb..cf5e19cf26 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspect.java
@@ -38,6 +38,7 @@ import org.alfresco.module.org_alfresco_module_rm.RecordsManagementPolicies;
import org.alfresco.module.org_alfresco_module_rm.model.behaviour.AbstractDisposableItem;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
+import org.alfresco.module.org_alfresco_module_rm.util.ContentBinDuplicationUtility;
import org.alfresco.repo.content.ContentServicePolicies;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
@@ -94,6 +95,9 @@ public class RecordAspect extends AbstractDisposableItem
/** quickShare service */
private QuickShareService quickShareService;
+ /** Utility class for duplicating content */
+ private ContentBinDuplicationUtility contentBinDuplicationUtility;
+
/** I18N */
private static final String MSG_CANNOT_UPDATE_RECORD_CONTENT = "rm.service.update-record-content";
@@ -130,6 +134,15 @@ public class RecordAspect extends AbstractDisposableItem
this.quickShareService = quickShareService;
}
+ /**
+ * Setter for content duplication utility class
+ * @param contentBinDuplicationUtility ContentBinDuplicationUtility
+ */
+ public void setContentBinDuplicationUtility(ContentBinDuplicationUtility contentBinDuplicationUtility)
+ {
+ this.contentBinDuplicationUtility = contentBinDuplicationUtility;
+ }
+
/**
* Behaviour to ensure renditions have the appropriate extended security.
*
@@ -356,7 +369,7 @@ public class RecordAspect extends AbstractDisposableItem
extendedSecurityService.remove(targetNodeRef);
//create a new content URL for the copy
- createNewContentURL(targetNodeRef);
+ contentBinDuplicationUtility.duplicate(targetNodeRef);
}
}
@@ -401,20 +414,7 @@ public class RecordAspect extends AbstractDisposableItem
if (!nodeService.getTargetAssocs(nodeRef, ContentModel.ASSOC_ORIGINAL).isEmpty() ||
!nodeService.getSourceAssocs(nodeRef, ContentModel.ASSOC_ORIGINAL).isEmpty())
{
- //disable versioning and auditing
- behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
- behaviourFilter.disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
- try
- {
- //create a new content URL for the copy/original node
- createNewContentURL(nodeRef);
- }
- finally
- {
- //enable versioning and auditing
- behaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
- behaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE);
- }
+ contentBinDuplicationUtility.duplicate(nodeRef);
}
return null;
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordComponentIdentifierAspect.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordComponentIdentifierAspect.java
index cdacc53990..d6d7b5db7d 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordComponentIdentifierAspect.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordComponentIdentifierAspect.java
@@ -63,8 +63,7 @@ import org.springframework.extensions.surf.util.I18NUtil;
)
public class RecordComponentIdentifierAspect extends BaseBehaviourBean
implements NodeServicePolicies.OnUpdatePropertiesPolicy,
- NodeServicePolicies.BeforeDeleteNodePolicy,
- CopyServicePolicies.OnCopyCompletePolicy
+ NodeServicePolicies.BeforeDeleteNodePolicy
{
/** I18N */
private static final String MSG_SET_ID = "rm.service.set-id";
@@ -177,31 +176,6 @@ public class RecordComponentIdentifierAspect extends BaseBehaviourBean
return new DoNothingCopyBehaviourCallback();
}
- @SuppressWarnings("rawtypes")
- @Override
- @Behaviour
- (
- kind = BehaviourKind.CLASS,
- notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT
- )
- public void onCopyComplete(QName classRef, NodeRef sourceNodeRef, NodeRef targetNodeRef, boolean copyToNewNode, Map copyMap)
- {
- //Generate the id for the copy
- String id = identifierService.generateIdentifier(
- nodeService.getType(nodeService.getPrimaryParent(targetNodeRef).getParentRef()),
- nodeService.getPrimaryParent(targetNodeRef).getParentRef());
-
- //We need to allow the id to be overwritten disable the policy protecting changes to the id
- behaviourFilter.disableBehaviour();
- try
- {
- nodeService.setProperty(targetNodeRef, PROP_IDENTIFIER, id);
- }
- finally
- {
- behaviourFilter.enableBehaviour();
- }
- }
/**
* Updates the uniqueness check using the values provided. If the after value is null
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspect.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspect.java
index f4712a8995..c41e937aa1 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspect.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspect.java
@@ -30,8 +30,10 @@ package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.relationship.Relationship;
import org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService;
+import org.alfresco.module.org_alfresco_module_rm.util.ContentBinDuplicationUtility;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
@@ -63,6 +65,11 @@ public class VersionRecordAspect extends BaseBehaviourBean
/** relationship service */
private RelationshipService relationshipService;
+ /**
+ * Utility class for duplicating content
+ */
+ private ContentBinDuplicationUtility contentBinDuplicationUtility;
+
/**
* @param recordableVersionService recordable version service
*/
@@ -79,6 +86,16 @@ public class VersionRecordAspect extends BaseBehaviourBean
this.relationshipService = relationshipService;
}
+ /**
+ * Setter for content duplication utility class
+ *
+ * @param contentBinDuplicationUtility ContentBinDuplicationUtility
+ */
+ public void setContentBinDuplicationUtility(ContentBinDuplicationUtility contentBinDuplicationUtility)
+ {
+ this.contentBinDuplicationUtility = contentBinDuplicationUtility;
+ }
+
/**
* If the record is a version record then delete the associated version entry
*
@@ -143,7 +160,11 @@ public class VersionRecordAspect extends BaseBehaviourBean
@Behaviour(kind = BehaviourKind.CLASS, notificationFrequency = NotificationFrequency.FIRST_EVENT)
public void beforeAddAspect(NodeRef nodeRef, QName qName)
{
- //create a new content URL for the version record
- createNewContentURL(nodeRef);
+ // if the node is the originating one the behaviour shouldn't be triggered
+ if (!nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_RECORD_ORIGINATING_DETAILS))
+ {
+ //create a new content URL for the version record
+ contentBinDuplicationUtility.duplicate(nodeRef);
+ }
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordFolderType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordFolderType.java
index 67a3ea526e..3d65ed4828 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordFolderType.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordFolderType.java
@@ -27,12 +27,9 @@
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
-import static org.alfresco.module.org_alfresco_module_rm.record.RecordUtils.generateRecordIdentifier;
-
import java.io.Serializable;
import java.util.Map;
-import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
@@ -203,18 +200,10 @@ public class RecordFolderType extends AbstractDisposableItem
@Override
public boolean getMustCopy(QName classQName, CopyDetails copyDetails)
{
- boolean result = true;
-
- if (nodeService.getType(copyDetails.getTargetParentNodeRef()).equals(TYPE_RECORD_FOLDER))
- {
- result = false;
- }
- else if (ArrayUtils.contains(unwantedAspects, classQName))
- {
- result = false;
- }
-
- return result;
+ boolean targetParentIsRecordFolder = nodeService.getType(copyDetails.getTargetParentNodeRef())
+ .equals(TYPE_RECORD_FOLDER);
+ boolean containsUnwantedAspect = ArrayUtils.contains(unwantedAspects, classQName);
+ return !(targetParentIsRecordFolder || containsUnwantedAspect);
}
};
}
@@ -253,7 +242,7 @@ public class RecordFolderType extends AbstractDisposableItem
}
}
- /**
+ /**
* On transaction commit
*
* @see org.alfresco.repo.node.NodeServicePolicies.OnCreateChildAssociationPolicy#onCreateChildAssociation(org.alfresco.service.cmr.repository.ChildAssociationRef, boolean)
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/compatibility/ModulePatchComponent.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/compatibility/ModulePatchComponent.java
index 3a38dd40a9..86f2769f96 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/compatibility/ModulePatchComponent.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/compatibility/ModulePatchComponent.java
@@ -27,12 +27,20 @@
package org.alfresco.module.org_alfresco_module_rm.patch.compatibility;
+import static org.alfresco.repo.module.ModuleVersionNumber.VERSION_ZERO;
+
+import java.io.Serializable;
+
import org.alfresco.module.org_alfresco_module_rm.patch.ModulePatchExecuterImpl;
+import org.alfresco.repo.admin.registry.RegistryKey;
+import org.alfresco.repo.admin.registry.RegistryService;
import org.alfresco.repo.module.AbstractModuleComponent;
+import org.alfresco.repo.module.ModuleComponentHelper;
+import org.alfresco.repo.module.ModuleVersionNumber;
import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
@@ -44,8 +52,12 @@ import org.apache.commons.logging.LogFactory;
@Deprecated
public abstract class ModulePatchComponent extends AbstractModuleComponent
{
+ private static final String REGISTRY_PATH_MODULES = "modules";
+ private static final String REGISTRY_PROPERTY_INSTALLED_VERSION = "installedVersion";
+ private static final String REGISTRY_PROPERTY_CURRENT_VERSION = "currentVersion";
+
/** logger */
- protected static final Log LOGGER = LogFactory.getLog(ModulePatchComponent.class);
+ protected static final Logger LOGGER = LoggerFactory.getLogger(ModulePatchComponent.class);
/** Retrying transaction helper */
protected RetryingTransactionHelper retryingTransactionHelper;
@@ -56,6 +68,9 @@ public abstract class ModulePatchComponent extends AbstractModuleComponent
/** module patch executer */
protected ModulePatchExecuterImpl modulePatchExecuter;
+ /** Registry service */
+ protected RegistryService registryService;
+
/**
* @param retryingTransactionHelper retrying transaction helper
*/
@@ -80,6 +95,14 @@ public abstract class ModulePatchComponent extends AbstractModuleComponent
this.modulePatchExecuter = modulePatchExecuter;
}
+ /**
+ * @param registryService Registry service
+ */
+ public void setRegistryService(RegistryService registryService)
+ {
+ this.registryService = registryService;
+ }
+
/**
* Init method
*/
@@ -96,47 +119,107 @@ public abstract class ModulePatchComponent extends AbstractModuleComponent
@Override
protected void executeInternal()
{
- try
+ //Get the new module version
+ String moduleId = modulePatchExecuter.getModuleId();
+ ModuleVersionNumber moduleNewVersionNumber = moduleService.getModule(moduleId).getModuleVersionNumber();
+
+ // Get the module details from the registry
+ ModuleVersionNumber moduleCurrentVersionNumber = getModuleVersionNumber(REGISTRY_PROPERTY_CURRENT_VERSION,
+ moduleId);
+ // Get the module patch component name
+ String moduleName = getName();
+ if (moduleCurrentVersionNumber.equals(VERSION_ZERO) ||
+ moduleCurrentVersionNumber.equals(moduleNewVersionNumber)) // No previous record of it
{
- if (LOGGER.isInfoEnabled())
+ LOGGER.info("Module patch component '{}' is skipped, no previous version found.", moduleName);
+ }
+ else
+ {
+ if (isVersionLaterThan(moduleCurrentVersionNumber, moduleNewVersionNumber))
{
- LOGGER.info("Module patch component '" + getName() + "' is executing ...");
+ LOGGER.info("Module patch component '{}' is skipped for upgrade from version {} to version {}",
+ moduleName, moduleCurrentVersionNumber, moduleNewVersionNumber);
}
-
- // execute path within an isolated transaction
- retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
+ else
{
- @Override
- public Void execute()
+ try
{
- behaviourFilter.disableBehaviour();
- try
+ LOGGER.info("Module patch component '{}' is executing ...", moduleName);
+
+ // execute path within an isolated transaction
+ retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback()
+
{
- executePatch();
- }
- finally
- {
- behaviourFilter.enableBehaviour();
- }
- return null;
+ @Override
+ public Void execute()
+ {
+ behaviourFilter.disableBehaviour();
+ try
+ {
+ executePatch();
+ }
+ finally
+ {
+ behaviourFilter.enableBehaviour();
+ }
+ return null;
+ }
+
+ }, false, true);
+
+ LOGGER.info(" ... completed module patch '{}'", moduleName);
+
+ }
+ catch (Exception exception)
+ {
+ // record the exception otherwise it gets swallowed
+ LOGGER.info(" ... error encountered. {}", exception.getMessage(), exception);
+ throw exception;
}
-
- }, false, true);
-
- if (LOGGER.isInfoEnabled())
- {
- LOGGER.info(" ... completed module patch '" + getName() + "'");
}
}
- catch (Exception exception)
+ }
+
+ /**
+ * Helper method to get the ModuleVersionNumber.
+ */
+ private ModuleVersionNumber getModuleVersionNumber(String registryProperty, String moduleId)
+ {
+ RegistryKey moduleKeyVersion = new RegistryKey(ModuleComponentHelper.URI_MODULES_1_0,
+ new String[]{REGISTRY_PATH_MODULES, moduleId, registryProperty});
+ Serializable moduleVersion = this.registryService.getProperty(moduleKeyVersion);
+
+ return new ModuleVersionNumber(moduleVersion.toString());
+ }
+
+ /**
+ * Helper method to determine if this is an upgrade from a version that already includes the early (v2.0, v2.1)
+ * patches.
+ *
+ */
+ private boolean isVersionLaterThan(ModuleVersionNumber moduleCurrentVersionNumber,
+ ModuleVersionNumber moduleNewVersionNumber)
+ {
+ // assume that the v2.0 and v2.1 patches should be run
+ boolean versionLaterThan = false;
+
+ // if this is an upgrade as opposed to a fresh install
+ if (moduleCurrentVersionNumber.compareTo(moduleNewVersionNumber) < 0)
{
- // record the exception otherwise it gets swallowed
- if (LOGGER.isInfoEnabled())
+ // if the installed version is later than the minimum version number of this patch
+ ModuleVersionNumber minVersion = this.getAppliesFromVersionNumber();
+ if (moduleCurrentVersionNumber.compareTo(minVersion) >= 0)
{
- LOGGER.info(" ... error encountered. " + exception.getMessage(), exception);
+ versionLaterThan = true;
}
- throw exception;
}
+ // v2.0 and v2.1 patches should not be run when both the current and the new version numbers are equals
+ else
+ {
+ versionLaterThan =true;
+ }
+
+ return versionLaterThan;
}
/**
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/ChildrenWithPropertyValuesQueryParams.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/PropertyValuesOfChildrenQueryParams.java
similarity index 79%
rename from rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/ChildrenWithPropertyValuesQueryParams.java
rename to rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/PropertyValuesOfChildrenQueryParams.java
index c5b5651e44..3eefd6b6bd 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/ChildrenWithPropertyValuesQueryParams.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/PropertyValuesOfChildrenQueryParams.java
@@ -26,19 +26,16 @@
*/
package org.alfresco.module.org_alfresco_module_rm.query;
-import java.util.Collection;
-
/**
- * Select parameter for select_CountChildrenWithPropertyValues.
+ * Select parameter for select_GetStringPropertyValuesOfChildren.
*
* @author Ana Manolache
* @since 2.6
*/
-public class ChildrenWithPropertyValuesQueryParams
+public class PropertyValuesOfChildrenQueryParams
{
private Long parentId;
private Long propertyQnameId;
- private Collection propertyValues;
public Long getParentId()
{
@@ -60,14 +57,5 @@ public class ChildrenWithPropertyValuesQueryParams
this.propertyQnameId = propertyQnameId;
}
- public Collection getPropertyValues()
- {
- return propertyValues;
- }
-
- public void setPropertyValues(Collection propertyValues)
- {
- this.propertyValues = propertyValues;
- }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java
index ea3a61c6dc..6810d68687 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java
@@ -27,13 +27,14 @@
package org.alfresco.module.org_alfresco_module_rm.query;
-
import java.util.List;
+import java.util.Set;
import org.alfresco.service.cmr.repository.NodeRef;
import java.util.Collection;
import org.alfresco.service.namespace.QName;
+
/**
* Records management query DAO
*
@@ -66,13 +67,17 @@ public interface RecordsManagementQueryDAO
/**
* Returns whether a given node contains children with one of the given values for the given property
+ * Returns distinct property values from children for the given property
*
* @param parent the parent to evaluate
* @param property the QName of the property to evaluate
- * @param propertyValues the list of values to look for
- * @return true if there is at least one child with one of the values from the list set on the given property
- * false otherwise
+ * @return list of distinct property values
*/
- public boolean hasChildrenWithPropertyValues(NodeRef parent, QName property, Collection propertyValues);
+ public Set getChildrenStringPropertyValues(NodeRef parent, QName property);
+ /**
+ * @param contentUrl the URL of the content url entity
+ * @return Set a set of nodes that reference the given content url
+ */
+ Set getNodeRefsWhichReferenceContentUrl(String contentUrl);
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java
index 7c7ac5fc6c..36131f95fa 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java
@@ -27,20 +27,28 @@
package org.alfresco.module.org_alfresco_module_rm.query;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.repo.domain.contentdata.ContentUrlEntity;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.domain.qname.QNameDAO;
import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.repo.version.Version2Model;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.mybatis.spring.SqlSessionTemplate;
/**
@@ -51,29 +59,43 @@ import org.mybatis.spring.SqlSessionTemplate;
*/
public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, RecordsManagementModel
{
+ /**
+ * logger
+ */
+ @SuppressWarnings("unused")
+ private static final Log logger = LogFactory.getLog(RecordsManagementQueryDAOImpl.class);
+
+ /**
+ * query names
+ */
private static final String COUNT_IDENTIFIER = "alfresco.query.rm.select_CountRMIndentifier";
+ private static final String GET_CHILDREN_PROPERTY_VALUES = "select_GetStringPropertyValuesOfChildren";
+ private static final String SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL = "select_NodeIdsWhichReferenceContentUrl";
private static final String SCHEDULED_FOLDERS = "alfresco.query.rm.select_RecordFoldersWithSchedules";
private static final String SCHEDULED_FOLDERS_COUNT = "alfresco.query.rm.select_RecordFoldersWithSchedulesCount";
- private static final String COUNT_CHILDREN_WITH_PROPERTY_VALUES = "select_CountChildrenWithPropertyValues";
- /** SQL session template */
+ /**
+ * SQL session template
+ */
protected SqlSessionTemplate template;
-
- /** QName DAO */
+
+ /**
+ * QName DAO
+ */
protected QNameDAO qnameDAO;
protected NodeDAO nodeDAO;
protected TenantService tenantService;
-
+
/**
- * @param sqlSessionTemplate SQL session template
+ * @param sqlSessionTemplate SQL session template
*/
- public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
+ public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate)
{
this.template = sqlSessionTemplate;
}
-
+
/**
- * @param qnameDAO qname DAO
+ * @param qnameDAO qname DAO
*/
public final void setQnameDAO(QNameDAO qnameDAO)
{
@@ -97,28 +119,143 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
public int getCountRmaIdentifier(String identifierValue)
{
int result = 0;
-
+
// lookup the id of the identifier property qname
Pair pair = qnameDAO.getQName(PROP_IDENTIFIER);
if (pair != null)
- {
+ {
// create query params
- Map params = new HashMap(2);
+ Map params = new HashMap<>(2);
params.put("qnameId", pair.getFirst());
params.put("idValue", identifierValue);
-
+
// return the number of rma identifiers found that match the passed value
- Integer count = (Integer)template.selectOne(COUNT_IDENTIFIER, params);
-
+ Integer count = (Integer) template.selectOne(COUNT_IDENTIFIER, params);
+
if (count != null)
{
result = count;
}
}
-
+
return result;
}
+ @Override
+ public Set getChildrenStringPropertyValues(NodeRef parent, QName property)
+ {
+ PropertyValuesOfChildrenQueryParams queryParams = new PropertyValuesOfChildrenQueryParams();
+
+ // Set the parent node id
+ Pair nodePair = nodeDAO.getNodePair(tenantService.getName(parent));
+ if (nodePair == null)
+ {
+ throw new InvalidNodeRefException("The parent node does not exist.", parent);
+ }
+ Long parentNodeId = nodePair.getFirst();
+ queryParams.setParentId(parentNodeId);
+
+ // Set the property qname id
+ Pair pair = qnameDAO.getQName(property);
+ if (pair == null)
+ {
+ return Collections.emptySet();
+ }
+ queryParams.setPropertyQnameId(pair.getFirst());
+
+ // Perform the query
+ return new HashSet<>(template.selectList(GET_CHILDREN_PROPERTY_VALUES, queryParams));
+
+ }
+
+ /**
+ * Get a set of node reference which reference the provided content URL
+ *
+ * @param String contentUrl content URL
+ * @return Set set of nodes that reference the provided content URL
+ */
+ @Override
+ public Set getNodeRefsWhichReferenceContentUrl(String contentUrl)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Getting nodes that reference content URL = " + contentUrl);
+ }
+
+ // create the content URL entity used to query for nodes
+ ContentUrlEntity contentUrlEntity = new ContentUrlEntity();
+ contentUrlEntity.setContentUrl(contentUrl.toLowerCase());
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Executing query " + SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL);
+ }
+
+ // Get all the node ids which reference the given content url
+ List nodeIds = template.selectList(SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL, contentUrlEntity);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Query " + SELECT_NODE_IDS_WHICH_REFERENCE_CONTENT_URL + " returned " + nodeIds.size() + " results");
+ }
+
+ // create a set of uuids which reference the content url
+ Set nodesReferencingContentUrl = new HashSet(nodeIds.size());
+ for (Long nodeId : nodeIds)
+ {
+ StringBuilder logMessage = null;
+ NodeRef nodeRefToAdd;
+
+ if (nodeId != null && nodeDAO.exists(nodeId))
+ {
+ if (logger.isDebugEnabled())
+ {
+ logMessage = new StringBuilder("Adding noderef ");
+ }
+
+ // if the referencing node is a version2Store reference to the content url, add the version 2 frozen node ref
+ NodeRef version2FrozenNodeRef = (NodeRef) nodeDAO.getNodeProperty(nodeId, Version2Model.PROP_QNAME_FROZEN_NODE_REF);
+ if (version2FrozenNodeRef != null && nodeDAO.exists(version2FrozenNodeRef))
+ {
+ nodeRefToAdd = version2FrozenNodeRef;
+
+ if (logger.isDebugEnabled())
+ {
+ logMessage.append(nodeRefToAdd)
+ .append(" (from version)");
+ }
+ }
+
+ // add the node ref of the referencing node
+ else
+ {
+ nodeRefToAdd = nodeDAO.getNodeIdStatus(nodeId)
+ .getNodeRef();
+ if (logger.isDebugEnabled())
+ {
+ logMessage.append(nodeRefToAdd);
+ }
+ }
+
+ nodesReferencingContentUrl.add(nodeRefToAdd);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug(logMessage.toString());
+ }
+ }
+ else
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Not adding " + nodeId + " (exist==false)");
+ }
+ }
+ }
+
+ return nodesReferencingContentUrl;
+ }
+
/**
* @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getRecordFoldersWithSchedules(Long, Long)
*/
@@ -147,40 +284,4 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO,
return results;
}
- @Override
- public boolean hasChildrenWithPropertyValues(NodeRef parent, QName property, Collection propertyValues)
- {
- if(propertyValues.isEmpty())
- {
- return false;
- }
-
- ChildrenWithPropertyValuesQueryParams queryParams = new ChildrenWithPropertyValuesQueryParams();
-
- // Set the parent node id
- Pair nodePair = nodeDAO.getNodePair(tenantService.getName(parent));
- if (nodePair == null)
- {
- throw new InvalidNodeRefException("The parent node does not exist.", parent);
- }
- Long parentNodeId = nodePair.getFirst();
- queryParams.setParentId(parentNodeId);
-
- // Set the property qname id
- Pair pair = qnameDAO.getQName(property);
- if (pair == null)
- {
- return false;
- }
- queryParams.setPropertyQnameId(pair.getFirst());
-
-
- // Set the property values
- queryParams.setPropertyValues(propertyValues);
-
- // Perform the query
- Long count = template.selectOne(COUNT_CHILDREN_WITH_PROPERTY_VALUES, queryParams);
- return count > 0;
- }
-
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
index bb6882482d..0d9b536a89 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java
@@ -45,6 +45,7 @@ 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.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.module.org_alfresco_module_rm.util.FileUtils;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authority.RMAuthority;
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
@@ -60,6 +61,8 @@ import org.apache.commons.lang.StringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/**
@@ -71,6 +74,8 @@ import org.springframework.extensions.surf.util.I18NUtil;
public class FilePlanRoleServiceImpl implements FilePlanRoleService,
RecordsManagementModel
{
+ /** Logger for the class. */
+ private static final Logger LOGGER = LoggerFactory.getLogger(FilePlanRoleServiceImpl.class);
/** I18N */
private static final String MSG_ALL_ROLES = "rm.role.all";
@@ -269,7 +274,7 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
{
throw new AlfrescoRuntimeException("Could not load default bootstrap roles configuration");
}
- array = new JSONArray(convertStreamToString(is));
+ array = new JSONArray(FileUtils.convertStreamToString(is));
}
catch (IOException ioe)
{
@@ -366,40 +371,6 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService,
}, AuthenticationUtil.getSystemUserName());
}
- /**
- * Helper method to convert a stream to a string.
- *
- * @param is input stream
- * @return {@link String} string
- * @throws IOException
- */
- public String convertStreamToString(InputStream is) throws IOException
- {
- /*
- * To convert the InputStream to String we use the BufferedReader.readLine()
- * method. We iterate until the BufferedReader return null which means
- * there's no more data to read. Each line will appended to a StringBuilder
- * and returned as String.
- */
- BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
- StringBuilder sb = new StringBuilder();
-
- String line = null;
- try
- {
- while ((line = reader.readLine()) != null)
- {
- sb.append(line + "\n");
- }
- }
- finally
- {
- try {is.close();} catch (IOException e) {}
- }
-
- return sb.toString();
- }
-
/**
* Helper method to check whether the current authority is a system role or not
*
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/AuditLogGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/AuditLogGet.java
index a73df97db2..9e880b37bd 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/AuditLogGet.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/AuditLogGet.java
@@ -57,6 +57,7 @@ public class AuditLogGet extends BaseAuditRetrievalWebScript
private static final String PARAM_EXPORT = "export";
private static final String ACCESS_AUDIT_CAPABILITY = "AccessAudit";
+ private static final int DEFAULT_VIEW_LOG_MAX_SIZE = 100;
/** Content Streamer */
protected ContentStreamer contentStreamer;
@@ -66,6 +67,9 @@ public class AuditLogGet extends BaseAuditRetrievalWebScript
/** File plan service */
protected FilePlanService filePlanService;
+
+ /** Maximum number of entries to be displayed in View Audit Log */
+ private int viewLogMaxSize;
/**
* @param contentStreamer
@@ -86,13 +90,22 @@ public class AuditLogGet extends BaseAuditRetrievalWebScript
/**
*
- * @param capabilityService Capability Service
+ * @param filePlanService File Plan Service
*/
public void setFilePlanService(FilePlanService filePlanService)
{
this.filePlanService = filePlanService;
}
+ /**
+ *
+ * @param viewLogMaxSize Maximum number of entries to be displayed in View Audit Log
+ */
+ public void setViewLogMaxSize(int viewLogMaxSize)
+ {
+ this.viewLogMaxSize = (viewLogMaxSize <= 0 ? DEFAULT_VIEW_LOG_MAX_SIZE: viewLogMaxSize);
+ }
+
@Override
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
{
@@ -100,7 +113,6 @@ public class AuditLogGet extends BaseAuditRetrievalWebScript
try
{
-
RecordsManagementAuditQueryParameters queryParams = parseQueryParameters(req);
ReportFormat reportFormat = parseReportFormat(req);
@@ -108,6 +120,13 @@ public class AuditLogGet extends BaseAuditRetrievalWebScript
{
throw new WebScriptException(Status.STATUS_FORBIDDEN, "Access denied because the user does not have the Access Audit capability");
}
+
+ // limit the number of audit log entries to be returned
+ if (queryParams.getMaxEntries() <= 0 || queryParams.getMaxEntries() > viewLogMaxSize)
+ {
+ queryParams.setMaxEntries(viewLogMaxSize);
+ }
+
// parse the parameters and get a file containing the audit trail
auditTrail = this.rmAuditService.getAuditTrailFile(queryParams, reportFormat);
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionAbstractBase.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionAbstractBase.java
index 946dd9902c..ff6a5540e9 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionAbstractBase.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionAbstractBase.java
@@ -27,6 +27,8 @@
package org.alfresco.module.org_alfresco_module_rm.script;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_COMBINE_DISPOSITION_STEP_CONDITIONS;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -49,6 +51,8 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
*/
public class DispositionAbstractBase extends AbstractRmWebScript
{
+
+ public final static String COMBINE_DISPOSITION_STEP_CONDITIONS = "combineDispositionStepConditions";
/**
* Parses the request and providing it's valid returns the DispositionSchedule object.
*
@@ -165,6 +169,11 @@ public class DispositionAbstractBase extends AbstractRmWebScript
model.put("events", eventNames);
}
+ if(getNodeService().getProperty(actionDef.getNodeRef(), PROP_COMBINE_DISPOSITION_STEP_CONDITIONS) != null)
+ {
+ model.put("combineDispositionStepConditions", getNodeService().getProperty(actionDef.getNodeRef(), PROP_COMBINE_DISPOSITION_STEP_CONDITIONS));
+ }
+
return model;
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionActionDefinitionPost.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionActionDefinitionPost.java
index 141f008c50..54f689fd93 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionActionDefinitionPost.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionActionDefinitionPost.java
@@ -133,6 +133,12 @@ public class DispositionActionDefinitionPost extends DispositionAbstractBase
json.getBoolean("eligibleOnFirstCompleteEvent") ? "or" : "and");
}
+ if (json.has(COMBINE_DISPOSITION_STEP_CONDITIONS))
+ {
+ props.put(RecordsManagementModel.PROP_COMBINE_DISPOSITION_STEP_CONDITIONS,
+ json.getBoolean(COMBINE_DISPOSITION_STEP_CONDITIONS));
+ }
+
if (json.has("location"))
{
props.put(RecordsManagementModel.PROP_DISPOSITION_LOCATION,
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionActionDefinitionPut.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionActionDefinitionPut.java
index 828171087d..6171f0cb1f 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionActionDefinitionPut.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionActionDefinitionPut.java
@@ -96,7 +96,6 @@ public class DispositionActionDefinitionPut extends DispositionAbstractBase
*
* @param actionDef The action definition to update
* @param json The JSON to use to create the action definition
- * @param schedule The DispositionSchedule the action definition belongs to
* @return The updated DispositionActionDefinition
*/
protected DispositionActionDefinition updateActionDefinition(DispositionActionDefinition actionDef,
@@ -132,6 +131,12 @@ public class DispositionActionDefinitionPut extends DispositionAbstractBase
json.getBoolean("eligibleOnFirstCompleteEvent") ? "or" : "and");
}
+ if (json.has(COMBINE_DISPOSITION_STEP_CONDITIONS))
+ {
+ props.put(RecordsManagementModel.PROP_COMBINE_DISPOSITION_STEP_CONDITIONS,
+ json.getBoolean(COMBINE_DISPOSITION_STEP_CONDITIONS));
+ }
+
if (json.has("location"))
{
props.put(RecordsManagementModel.PROP_DISPOSITION_LOCATION,
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/ClassificationReasonsUtil.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/ClassificationReasonsUtil.java
new file mode 100644
index 0000000000..ad9a50e6bc
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/ClassificationReasonsUtil.java
@@ -0,0 +1,86 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.script.slingshot;
+
+import static org.alfresco.model.ContentModel.PROP_NAME;
+import static org.alfresco.service.namespace.QName.createQName;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Method to replace the plain text classification reason id with the correct nodeRef during record search
+ * @author Ross Gale
+ * @since 2.7
+ */
+public class ClassificationReasonsUtil extends SearchUtil
+{
+
+ public static final String CR_URI = "http://www.alfresco.org/model/securitymarks/1.0";
+ public static final QName CLASSIFICATION_REASONS_CONTAINER = createQName(CR_URI,"classificationReasonsContainer");
+ public static final QName PROP_CLASSIFICATION_REASON_CODE = createQName(CR_URI, "classificationReasonCode");
+ public static final String REASONS_KEY = "clf:classificationReasons:";
+
+ /**
+ * Replace plain text reason id with nodeRef
+ * @param searchQuery String e.g. clf:classificationReasons:1.4(a)
+ * @return String e.g. clf:classificationReasons:5cc6d344-fa94-4370-9c81-d947b7e8f2ac
+ */
+ public String replaceReasonWithNodeRef(String searchQuery)
+ {
+ List queries = new ArrayList<>(Arrays.asList(searchQuery.split(" ")));
+ StringBuilder stringBuilder = new StringBuilder();
+ for (String queryToEdit : queries)
+ {
+ if(queryToEdit.contains(REASONS_KEY))
+ {
+ for (String reasonId : retrieveAllNodeIds(getRootContainer(CLASSIFICATION_REASONS_CONTAINER)))
+ {
+ NodeRef reasonNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, reasonId);
+ Map properties = nodeService.getProperties(reasonNodeRef);
+ if (queryToEdit.equals(REASONS_KEY + properties.get(PROP_CLASSIFICATION_REASON_CODE).toString()) ||
+ queryToEdit.equals(REASONS_KEY +"\""+ properties.get(PROP_CLASSIFICATION_REASON_CODE).toString() + "\""))
+ {
+ queryToEdit = REASONS_KEY + properties.get(PROP_NAME).toString();
+ break;
+ }
+ }
+ }
+ stringBuilder.append(queryToEdit).append(" ");
+ }
+ return stringBuilder.toString();
+ }
+
+
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java
index 9ef7af64fe..4b5f18819f 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java
@@ -27,6 +27,8 @@
package org.alfresco.module.org_alfresco_module_rm.script.slingshot;
+import static org.alfresco.module.org_alfresco_module_rm.script.slingshot.ClassificationReasonsUtil.REASONS_KEY;
+
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
@@ -53,6 +55,8 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
@@ -66,6 +70,8 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
*/
public class RMSearchGet extends DeclarativeWebScript
{
+ /** Logger for the class. */
+ private static final Logger LOGGER = LoggerFactory.getLogger(RMSearchGet.class);
/** URL Parameters */
private static final String PARAM_QUERY = "query";
private static final String PARAM_SORTBY = "sortby";
@@ -96,6 +102,12 @@ public class RMSearchGet extends DeclarativeWebScript
/** Person data cache */
private Map personDataCache = null;
+ /** Utility class for record categories */
+ private RecordCategoryUtil recordCategoryUtil;
+
+ /** Utility class for classification reasons (enterprise only) */
+ private ClassificationReasonsUtil classificationReasonsUtil;
+
/**
* @param recordsManagementSearchService records management search service
*/
@@ -144,6 +156,19 @@ public class RMSearchGet extends DeclarativeWebScript
this.permissionService = permissionService;
}
+ /**
+ * @param recordCategoryUtil utility class for record categories
+ */
+ public void setRecordCategoryUtil(RecordCategoryUtil recordCategoryUtil)
+ {
+ this.recordCategoryUtil = recordCategoryUtil;
+ }
+
+ public void setClassificationReasonsUtil(ClassificationReasonsUtil classificationReasonsUtil)
+ {
+ this.classificationReasonsUtil = classificationReasonsUtil;
+ }
+
/**
* @param personService person service
*/
@@ -183,6 +208,12 @@ public class RMSearchGet extends DeclarativeWebScript
String filters = req.getParameter(PARAM_FILTERS);
// TODO this is optional
+ //Replace any plain text reason ids with the appropriate node reference
+ if(query.contains(REASONS_KEY))
+ {
+ query = classificationReasonsUtil.replaceReasonWithNodeRef(query);
+ }
+
// Convert into a rm search parameter object
RecordsManagementSearchParameters searchParameters =
SavedSearchDetailsCompatibility.createSearchParameters(filters, new String[]{",", "/"}, sortby, namespaceService);
@@ -211,7 +242,10 @@ public class RMSearchGet extends DeclarativeWebScript
Item item = new Item(pair.getFirst(), pair.getSecond());
items.add(item);
}
- catch(Exception e) {}
+ catch(Exception e)
+ {
+ LOGGER.debug("Ignoring failed attempt to add item to search results.", e);
+ }
}
// Return model
@@ -240,6 +274,7 @@ public class RMSearchGet extends DeclarativeWebScript
private String createdBy;
private Map nodeProperties;
private Map properties;
+ private String recordCategoryId;
public Item(NodeRef parent, NodeRef nodeRef)
{
@@ -333,6 +368,7 @@ public class RMSearchGet extends DeclarativeWebScript
properties.put(prefixName, entry.getValue());
}
}
+ properties.put("rma_recordCategoryIdentifier", recordCategoryUtil.getCategoryIdFromNodeId(nodeRef, false));
}
private String getDisplayName(String userName)
@@ -438,5 +474,15 @@ public class RMSearchGet extends DeclarativeWebScript
{
return properties;
}
+
+ public String getRecordCategoryId()
+ {
+ return recordCategoryId;
+ }
+
+ public void setRecordCategoryId(String recordCategoryId)
+ {
+ this.recordCategoryId = recordCategoryId;
+ }
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RecordCategoryUtil.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RecordCategoryUtil.java
new file mode 100644
index 0000000000..cf1dec0d02
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RecordCategoryUtil.java
@@ -0,0 +1,86 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.script.slingshot;
+
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_IDENTIFIER;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.TYPE_RECORD_CATEGORY;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.TYPE_RECORD_FOLDER;
+
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.Path;
+import org.alfresco.service.cmr.repository.Path.ChildAssocElement;
+
+/**
+ * Utility class for record categories
+ * @author Ross Gale
+ * @since 2.7
+ */
+public class RecordCategoryUtil
+{
+ /**
+ * Node service
+ */
+ private NodeService nodeService;
+
+ /**
+ * Setter for the node service
+ * @param nodeService Node service
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Return the record category id for a file plan element
+ * @param nodeRef the node reference of the file plan element
+ * @param includeFolders return an id for records, folders and categories
+ * @return Record category identifier
+ */
+ public String getCategoryIdFromNodeId(NodeRef nodeRef, boolean includeFolders)
+ {
+ if(!includeFolders)
+ {
+ if (nodeService.getType(nodeRef).equals(TYPE_RECORD_FOLDER) || nodeService.getType(nodeRef).equals(TYPE_RECORD_CATEGORY))
+ {
+ return null;
+ }
+ }
+ //Search for the first category from the end of the path to save time
+ Path path = nodeService.getPath(nodeRef);
+ for(int x = path.size()-1; x >= 0; x--)
+ {
+ NodeRef ref = ((ChildAssocElement) path.get(x)).getRef().getChildRef();
+ if (nodeService.getType(ref).equals(TYPE_RECORD_CATEGORY))
+ {
+ return nodeService.getProperty(ref, PROP_IDENTIFIER).toString();
+ }
+ }
+ return null;
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/SearchUtil.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/SearchUtil.java
new file mode 100644
index 0000000000..5917d48c90
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/SearchUtil.java
@@ -0,0 +1,103 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.script.slingshot;
+
+import static org.alfresco.model.ContentModel.ASSOC_CHILDREN;
+import static org.alfresco.model.ContentModel.TYPE_CONTAINER;
+import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
+
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * Parent class for records search utilities
+ *
+ * @author Ross Gale
+ * @since 2.7
+ */
+public class SearchUtil
+{
+ /**
+ * Node service
+ */
+ protected NodeService nodeService;
+
+ /**
+ * Setter for node service
+ *
+ * @param nodeService Node service
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * Use a container node ref and return the nodeIds of the contents
+ *
+ * @param nodeRef container
+ * @return list of nodeIds
+ */
+ protected Set retrieveAllNodeIds(NodeRef nodeRef)
+ {
+ List childAssocRefs = nodeService.getChildAssocs(nodeRef);
+ return childAssocRefs.stream().map(assoc -> assoc.getChildRef().getId()).collect(Collectors.toSet());
+ }
+
+ /**
+ * Helper method to get the classification reason root container.
+ * The method creates the container if it doesn't already exist.
+ *
+ * @return reference to the classification reason root container
+ */
+ protected NodeRef getRootContainer(QName container)
+ {
+ NodeRef rootNodeRef = nodeService.getRootNode(STORE_REF_WORKSPACE_SPACESSTORE);
+ List assocRefs = nodeService.getChildAssocs(rootNodeRef, ASSOC_CHILDREN, container);
+
+ if (assocRefs.isEmpty())
+ {
+ return nodeService.createNode(rootNodeRef, ASSOC_CHILDREN, container, TYPE_CONTAINER).getChildRef();
+ }
+ else if (assocRefs.size() != 1)
+ {
+ throw new AlfrescoRuntimeException("Only one container is allowed.");
+ }
+ else
+ {
+ return assocRefs.iterator().next().getChildRef();
+ }
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtility.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtility.java
new file mode 100644
index 0000000000..68a0bab6c3
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ContentBinDuplicationUtility.java
@@ -0,0 +1,142 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.util;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO;
+import org.alfresco.repo.policy.BehaviourFilter;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.ContentWriter;
+import org.alfresco.service.cmr.repository.NodeRef;
+
+import java.util.Set;
+
+/**
+ * Utility class to duplicate the content of a node without triggering the audit or versioning behaviours
+ * @author Ross Gale
+ * @since 2.7.2
+ */
+public class ContentBinDuplicationUtility extends ServiceBaseImpl
+{
+
+ /**
+ * Behaviour filter
+ */
+ private BehaviourFilter behaviourFilter;
+
+ /**
+ * Provides methods for accessing and transforming content.
+ */
+ private ContentService contentService;
+
+ /** Records Management Query DAO */
+ private RecordsManagementQueryDAO recordsManagementQueryDAO;
+
+ /**
+ * Setter for behaviour filter
+ * @param behaviourFilter BehaviourFilter
+ */
+ public void setBehaviourFilter(BehaviourFilter behaviourFilter)
+ {
+ this.behaviourFilter = behaviourFilter;
+ }
+
+ /**
+ * Setter for content service
+ * @param contentService ContentService
+ */
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
+ /**
+ * Setter for the Records Management QueryDAO
+ *
+ * @param recordsManagementQueryDAO The RM query DAO to set
+ */
+ public void setRecordsManagementQueryDAO(RecordsManagementQueryDAO recordsManagementQueryDAO)
+ {
+ this.recordsManagementQueryDAO = recordsManagementQueryDAO;
+ }
+
+ /**
+ * Determines whether the bin file for a given node has at least one other reference to it
+ * Will return true if the binary exists and is referenced by at least one other node
+ * @param nodeRef Node with the binary in question
+ * @return boolean for if the bin has at least one other reference to it
+ */
+ public boolean hasAtLeastOneOtherReference(NodeRef nodeRef)
+ {
+ boolean hasAtLeastOneOtherReference = false;
+ String contentUrl = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT).getContentUrl();
+
+ Set referencesToContentNode = recordsManagementQueryDAO.getNodeRefsWhichReferenceContentUrl(contentUrl);
+ if (referencesToContentNode.size() > 1)
+ {
+ hasAtLeastOneOtherReference = true;
+ }
+ return hasAtLeastOneOtherReference;
+ }
+
+ /**
+ * Duplicate the content of a node without triggering the audit or versioning behaviours
+ *
+ * @param nodeRef The node with the content to duplicate
+ */
+ public void duplicate(NodeRef nodeRef)
+ {
+ //disabling versioning and auditing
+ behaviourFilter.disableBehaviour();
+ try
+ {
+ //create a new content URL for the copy/original node
+ updateContentProperty(nodeRef);
+ }
+ finally
+ {
+ //enable versioning and auditing
+ behaviourFilter.enableBehaviour();
+ }
+ }
+
+ /**
+ * Helper to update the content property for the node
+ *
+ * @param nodeRef the node
+ */
+ private void updateContentProperty(NodeRef nodeRef)
+ {
+ ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
+ if (reader != null)
+ {
+ ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
+ writer.putContent(reader);
+ }
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/FileUtils.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/FileUtils.java
new file mode 100644
index 0000000000..aff77ddb61
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/FileUtils.java
@@ -0,0 +1,64 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+
+/**
+ * Utility class for working with files.
+ *
+ * @author Roxana Lucanu
+ * @since 2.7
+ */
+public class FileUtils
+{
+ /**
+ * Helper method to convert a stream to a string.
+ *
+ * @param is input stream
+ * @return {@link String} string
+ * @throws IOException
+ */
+ public static String convertStreamToString(InputStream is) throws IOException
+ {
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8"))))
+ {
+ StringBuilder sb = new StringBuilder();
+ String line = null;
+
+ while ((line = reader.readLine()) != null)
+ {
+ sb.append(line + "\n");
+ }
+ return sb.toString();
+ }
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtils.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtils.java
index 026275a5ab..a1828d6ad7 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtils.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/RMCollectionUtils.java
@@ -39,6 +39,8 @@ import java.util.Set;
import com.google.common.collect.ImmutableSet;
+import org.apache.commons.collections.CollectionUtils;
+
/**
* Various common helper methods for Collections. This class is probably only appropriate for use with relatively
* small collections as it has not been optimised for dealing with large collections.
@@ -226,4 +228,21 @@ public final class RMCollectionUtils
}
return ImmutableSet.copyOf(collection);
}
+
+ /**
+ * Check if a property is null or an empty collection. Note that this is the same as
+ * {org.apache.commons.collections.CollectionUtils.isEmpty(Collection)}, except that it takes a Serializable rather
+ * than a Collection. This avoids awkward casting exceptions when working with properties.
+ *
+ * @param value The (probably Collection) value to check.
+ * @return true if the supplied value is null or an empty collection.
+ */
+ public static boolean isEmpty(Serializable value)
+ {
+ if (value instanceof Collection)
+ {
+ return CollectionUtils.isEmpty((Collection) value);
+ }
+ return (value == null);
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java
index 8fc5094b05..f7a58ea1ff 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java
@@ -31,7 +31,7 @@ import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
-import org.alfresco.model.ContentModel;
+
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldService;
@@ -39,9 +39,7 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.rendition.RenditionService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
-import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
-import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
@@ -554,30 +552,4 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
result.add(nodeService.getType(nodeRef));
return result;
}
-
- /**
- * Helper to update the given content property for the node
- *
- * @param nodeRef the node
- * @param contentProperty the property to be updated
- */
- protected void updateContentProperty(NodeRef nodeRef, QName contentProperty)
- {
- ContentReader reader = contentService.getReader(nodeRef, contentProperty);
- if (reader != null)
- {
- ContentWriter writer = contentService.getWriter(nodeRef, contentProperty, true);
- writer.putContent(reader);
- }
- }
-
- /**
- * Helper to create a new content URL for the node
- *
- * @param nodeRef the node
- */
- protected void createNewContentURL(NodeRef nodeRef)
- {
- updateContentProperty(nodeRef, ContentModel.PROP_CONTENT);
- }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java
index e5082d7f0e..b9abf212ac 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/roles/DynamicAuthoritiesGet.java
@@ -358,7 +358,7 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM
res.getWriter().write(")");
}
}
- catch (Throwable e)
+ catch (Exception e)
{
if (logger.isDebugEnabled())
{
@@ -416,7 +416,7 @@ public class DynamicAuthoritiesGet extends AbstractWebScript implements RecordsM
protected Long getBatchSizeParameter(WebScriptRequest req)
{
String batchSizeStr = req.getParameter(BATCH_SIZE);
- Long size = 0L;
+ Long size;
if (StringUtils.isBlank(batchSizeStr))
{
logger.info(MESSAGE_BATCHSIZE_IS_MANDATORY);
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/FilePlanComponentsApiUtils.java b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/FilePlanComponentsApiUtils.java
index 9cae31c6e3..52eab95b0a 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/FilePlanComponentsApiUtils.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/rm/rest/api/impl/FilePlanComponentsApiUtils.java
@@ -27,6 +27,7 @@
package org.alfresco.rm.rest.api.impl;
+import static org.alfresco.model.ContentModel.TYPE_FOLDER;
import static org.alfresco.module.org_alfresco_module_rm.util.RMParameterCheck.checkNotBlank;
import static org.alfresco.util.ParameterCheck.mandatory;
@@ -126,6 +127,8 @@ public class FilePlanComponentsApiUtils
public static final String UNFILED_ALIAS = "-unfiled-";
public static final String HOLDS_ALIAS = "-holds-";
public static final String RM_SITE_ID = "rm";
+ public static final List CONTAINERS_FOR_CLASSIFIABLE_CHILDREN_ALIAS = Arrays.asList(
+ FILE_PLAN_ALIAS, UNFILED_ALIAS);
//public static String PARAM_RELATIVE_PATH = "relativePath";
// excluded properties
@@ -258,9 +261,71 @@ public class FilePlanComponentsApiUtils
ParameterCheck.mandatoryString("nodeId", nodeId);
ParameterCheck.mandatory("expectedNodeType", expectedNodeType);
- /*
- * Lookup by placeholder
- */
+ NodeRef nodeRef = lookupByPlaceholder(nodeId);
+
+ QName nodeType = nodeService.getType(nodeRef);
+ if (!nodeType.equals(expectedNodeType))
+ {
+ throw new InvalidArgumentException("The given id:'" + nodeId + "' (nodeType:" + nodeType.toString()
+ + ") is not valid for this endpoint. Expected nodeType is:" + expectedNodeType.toString());
+ }
+
+ if(StringUtils.isNotBlank(relativePath))
+ {
+ nodeRef = lookupAndValidateRelativePath(nodeRef, relativePath, readOnlyRelativePath, expectedNodeType);
+ }
+ return nodeRef;
+ }
+
+ /**
+ * look up node by id and validate node type is suitable container
+ *
+ * @param nodeId
+ * @return
+ */
+ public NodeRef validateAndLookUpContainerNode(String nodeId, List allowedPlaceholders)
+ {
+ ParameterCheck.mandatoryString("nodeId", nodeId);
+
+ NodeRef nodeRef = lookupByAllowedPlaceholders(nodeId, allowedPlaceholders);
+ QName nodeType = nodeService.getType(nodeRef);
+ if(!dictionaryService.isSubClass(nodeType, TYPE_FOLDER))
+ {
+ throw new InvalidArgumentException("The given id:'" + nodeId + "' (nodeType:" + nodeType.toString()
+ + ") is not valid for this endpoint. Expected nodeType is:" + TYPE_FOLDER.toString());
+ }
+
+ return nodeRef;
+ }
+ /**
+ * Lookup node by placeholder from allowed placeholder list
+ *
+ * @param nodeId
+ * @param allowedPlaceholders
+ * @return NodeRef for corresponding id
+ */
+ public NodeRef lookupByAllowedPlaceholders(String nodeId, List allowedPlaceholders)
+ {
+ NodeRef nodeRef;
+ if (allowedPlaceholders.contains(nodeId))
+ {
+ nodeRef = lookupByPlaceholder(nodeId);
+ }
+ else
+ {
+ nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
+ }
+ return nodeRef;
+ }
+
+ /**
+ * Lookup node by placeholder
+ *
+ * @param nodeId
+ * @return NodeRef for corresponding id
+ */
+ public NodeRef lookupByPlaceholder(String nodeId)
+ {
NodeRef nodeRef;
if (nodeId.equals(FILE_PLAN_ALIAS))
{
@@ -314,18 +379,7 @@ public class FilePlanComponentsApiUtils
{
nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, nodeId);
}
-
- QName nodeType = nodeService.getType(nodeRef);
- if (!nodeType.equals(expectedNodeType))
- {
- throw new InvalidArgumentException("The given id:'" + nodeId + "' (nodeType:" + nodeType.toString()
- + ") is not valid for this endpoint. Expected nodeType is:" + expectedNodeType.toString());
- }
-
- if(StringUtils.isNotBlank(relativePath))
- {
- nodeRef = lookupAndValidateRelativePath(nodeRef, relativePath, readOnlyRelativePath, expectedNodeType);
- }
+
return nodeRef;
}
@@ -584,7 +638,7 @@ public class FilePlanComponentsApiUtils
}
/**
* Helper method that converts a map of String properties into a map of QName properties
- * @param props
+ * @param properties
* @return a map of properties
*/
public Map mapToNodeProperties(Map properties)
@@ -931,7 +985,7 @@ public class FilePlanComponentsApiUtils
}
String pathStr = null;
- if (pathElements.size() > 0)
+ if (!pathElements.isEmpty())
{
StringBuilder sb = new StringBuilder(120);
for (PathInfo.ElementInfo e : pathElements)
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4804Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4804Test.java
index e6ed70983b..5de7ee766c 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4804Test.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4804Test.java
@@ -46,8 +46,6 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.extensions.webscripts.GUID;
-import javax.xml.soap.Node;
-
/**
* Integration test for RM-4804
*
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM5225Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM5225Test.java
new file mode 100644
index 0000000000..7d73d4ba71
--- /dev/null
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM5225Test.java
@@ -0,0 +1,80 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
+
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.springframework.extensions.webscripts.GUID;
+
+/**
+ * Integration test for RM-5225
+ *
+ * Copy of record from a RM site does not append the correct id at the end of the record name.
+ */
+public class RM5225Test extends BaseRMTestCase
+{
+ /**
+ * Given the RM site, a record category created in the fileplan, a record folder containing a record
+ * When we create a copy from the existing record
+ * Then the created record name contains both the name of the record from which it was created and the unique identifier of the current record.
+ */
+ public void testCopyToRecord()
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ private NodeRef record;
+ private NodeRef copiedRecord;
+
+ public void given()
+ {
+
+ /** Create record category. */
+ NodeRef recordCategory = filePlanService.createRecordCategory(filePlan, GUID.generate());
+
+ /** Create record folder. */
+ NodeRef recordFolder = recordFolderService.createRecordFolder(recordCategory, GUID.generate());
+
+ /** File record. */
+ record = utils.createRecord(recordFolder, GUID.generate());
+ }
+
+ public void when()
+ {
+ /** Create a copy of the original record */
+ copiedRecord = recordService.createRecordFromCopy(filePlan, record);
+ }
+
+ public void then()
+ {
+ /** Check if the copied record contains the name of the record from which is copied. */
+ assertTrue(nodeService.getProperty(copiedRecord, PROP_NAME).toString().contains(nodeService.getProperty(record, PROP_NAME).toString()));
+ /** Check if the copied record name contains its unique id. */
+ assertTrue(nodeService.getProperty(copiedRecord, PROP_NAME).toString().contains(nodeService.getProperty(copiedRecord, PROP_IDENTIFIER).toString()));
+ }
+ });
+ }
+}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordsManagementAuditServiceImplTest.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordsManagementAuditServiceImplTest.java
index 39b7cad51b..b8e5ec7120 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordsManagementAuditServiceImplTest.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordsManagementAuditServiceImplTest.java
@@ -33,6 +33,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditEntry;
@@ -78,18 +80,18 @@ public class RecordsManagementAuditServiceImplTest extends BaseRMTestCase
@Override
public Void run() throws Exception
{
- // test start time recorded
- testStartTime = new Date();
+ // test start time recorded
+ testStartTime = new Date();
- // Stop and clear the log
- rmAuditService.stopAuditLog(filePlan);
- rmAuditService.clearAuditLog(filePlan);
- rmAuditService.startAuditLog(filePlan);
+ // Stop and clear the log
+ rmAuditService.stopAuditLog(filePlan);
+ rmAuditService.clearAuditLog(filePlan);
+ rmAuditService.startAuditLog(filePlan);
- // check that audit service is started
- assertTrue(rmAuditService.isAuditLogEnabled(filePlan));
+ // check that audit service is started
+ assertTrue(rmAuditService.isAuditLogEnabled(filePlan));
- return null;
+ return null;
}
});
}
@@ -198,7 +200,7 @@ public class RecordsManagementAuditServiceImplTest extends BaseRMTestCase
}
});
}
-
+
/**
* Test getAuditTrail method and parameter filters.
*/
@@ -459,6 +461,116 @@ public class RecordsManagementAuditServiceImplTest extends BaseRMTestCase
assertTrue("Expected to hit successful login attempt for Charles Dickons (cdickons)", found);
}
+ /**
+ * Given I have deleted a user
+ * When I will get the RM audit filter by delete user event
+ * Then there will be an entry for the deleted user
+ * And the audit entry has the username property value audited
+ * @throws Exception
+ */
+ @org.junit.Test
+ public void testAuditForDeletedUser() throws Exception
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ final static String DELETE_USER_AUDIT_EVENT = "Delete Person";
+ String userName = "auditDeleteUser";
+ NodeRef user;
+ List entry;
+
+ @Override
+ public void given() throws Exception
+ {
+ // create a user
+ user = createPerson(userName);
+ personService.deletePerson(userName);
+ }
+
+ @Override
+ public void when() throws Exception
+ {
+ // set the audit wuery param
+ RecordsManagementAuditQueryParameters params = new RecordsManagementAuditQueryParameters();
+ params.setEvent(DELETE_USER_AUDIT_EVENT);
+
+ // get the audit events for "Delete Person"
+ entry = getAuditTrail(params, 1, ADMIN_USER);
+ }
+
+ @Override
+ public void then() throws Exception
+ {
+ assertEquals("Delete user event is not audited.", DELETE_USER_AUDIT_EVENT, entry.get(0).getEvent());
+ assertEquals(user.getId(), entry.get(0).getNodeName());
+ assertEquals("Unexpected nr of properties audited for cm:person type when deleting a user.",
+ 1, entry.get(0).getBeforeProperties().size());
+ assertEquals("Wrong value for username property is audited",
+ userName, entry.get(0).getBeforeProperties().get(ContentModel.PROP_USERNAME));
+ }
+ @Override
+ public void after()
+ {
+ // Stop and delete all entries
+ rmAuditService.stopAuditLog(filePlan);
+ rmAuditService.clearAuditLog(filePlan);
+ }
+
+ });
+ }
+
+ /**
+ * Given I have created a user
+ * When I will get the RM audit filter by create user event
+ * Then there will be an entry for the created user
+ *
+ * @throws Exception
+ */
+ @org.junit.Test
+ public void testAuditForCreateUser() throws Exception
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ final static String CREATE_USER_AUDIT_EVENT = "Create Person";
+ String userName = "auditCreateUser";
+ NodeRef user;
+ List entry;
+
+ @Override
+ public void given() throws Exception
+ {
+ // create a user
+ user = createPerson(userName);
+ }
+
+ @Override
+ public void when() throws Exception
+ {
+ // set the audit query param
+ RecordsManagementAuditQueryParameters params = new RecordsManagementAuditQueryParameters();
+ params.setEvent(CREATE_USER_AUDIT_EVENT);
+
+ // get the audit events for "Create Person"
+ entry = getAuditTrail(params, 1, ADMIN_USER);
+ }
+
+ @Override
+ public void then() throws Exception
+ {
+ assertEquals("Create user event is not audited.",
+ CREATE_USER_AUDIT_EVENT, entry.get(0).getEvent());
+ }
+
+ @Override
+ public void after()
+ {
+ // Stop and delete all entries
+ rmAuditService.stopAuditLog(filePlan);
+ rmAuditService.clearAuditLog(filePlan);
+ }
+
+ });
+ }
+
/** === Helper methods === */
private List getAuditTrail(String asUser)
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordsManagementQueryDAOImplTest.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordsManagementQueryDAOImplTest.java
index 556b497f5a..66f1155424 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordsManagementQueryDAOImplTest.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordsManagementQueryDAOImplTest.java
@@ -27,8 +27,9 @@
package org.alfresco.module.org_alfresco_module_rm.test.legacy.service;
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
@@ -94,12 +95,12 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
}
/**
- * Given a folder containing 3 files with the descriptions set
- * When I check if the folder contains children having the description of file2 or file2
- * Then the answer is positive
+ * Given a folder containing 3 files with distinct descriptions set
+ * When I get the children property values
+ * Then the answer contains all distinct property values set
*/
@org.junit.Test
- public void testHasChildrenWithPropertyValues_someChildrenWithValues() throws Exception
+ public void testGetChildrenWithPropertyValues_childrenWithValues() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
@@ -110,8 +111,7 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
String propValue1 = "descr1"; // set on file1
String propValue2 = "descr2"; // set on file2
String propValue3 = "descr3"; // set on file3
- String propValue4 = "descr4"; // not set on any file
- Boolean result;
+ Set propertyValues;
@Override
public void given() throws Exception
@@ -130,13 +130,72 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
@Override
public void when() throws Exception
{
- result = queryDAO.hasChildrenWithPropertyValues(parentFolder, PROP_DESCRIPTION, Arrays.asList(propValue1, propValue2, propValue4));
+ propertyValues = queryDAO.getChildrenStringPropertyValues(parentFolder, PROP_DESCRIPTION);
}
@Override
public void then() throws Exception
{
- assertTrue(result);
+ Set expectedValues = ImmutableSet.of(propValue1, propValue2, propValue3);
+ assertEquals(propertyValues.size(), expectedValues.size());
+ assertTrue(propertyValues.containsAll(expectedValues));
+ }
+
+ @Override
+ public void after() throws Exception
+ {
+ if (parentFolder != null && nodeService.exists(parentFolder))
+ {
+ nodeService.deleteNode(parentFolder);
+ }
+ }
+ });
+ }
+
+ /**
+ * Given a folder containing 3 files only some have description set
+ * When I get the children property values
+ * Then the answer contains only the descriptions set
+ */
+ @org.junit.Test
+ public void testGetChildrenWithPropertyValues_someChildrenWithValues() throws Exception
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ NodeRef parentFolder;
+ NodeRef file1;
+ NodeRef file2;
+ NodeRef file3;
+ String propValue1 = "descr1"; // set on file1
+ String propValue2 = "descr2"; // set on file2
+ Set propertyValues;
+
+
+ @Override
+ public void given() throws Exception
+ {
+ setupCollaborationSiteTestDataImpl();
+ parentFolder = fileFolderService.create(documentLibrary, GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
+ file1 = fileFolderService.create(parentFolder, GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
+ file2 = fileFolderService.create(parentFolder, GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
+ file3 = fileFolderService.create(parentFolder, GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
+
+ nodeService.setProperty(file1, PROP_DESCRIPTION, propValue1);
+ nodeService.setProperty(file2, PROP_DESCRIPTION, propValue2);
+ }
+
+ @Override
+ public void when() throws Exception
+ {
+ propertyValues = queryDAO.getChildrenStringPropertyValues(parentFolder, PROP_DESCRIPTION);
+ }
+
+ @Override
+ public void then() throws Exception
+ {
+ Set expectedValues = ImmutableSet.of(propValue1, propValue2);
+ assertEquals(propertyValues.size(), expectedValues.size());
+ assertTrue(propertyValues.containsAll(expectedValues));
}
@Override
@@ -152,11 +211,11 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
/**
* Given a folder containing 3 files with the descriptions unset
- * When I check if the folder contains children having certain descriptions
- * Then the answer is negative
+ * When I get the children property values
+ * Then empty list is returned
*/
@org.junit.Test
- public void testHasChildrenWithPropertyValues_propertyNotSetOnChildren() throws Exception
+ public void testGetChildrenWithPropertyValues_propertyNotSetOnChildren() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
@@ -164,7 +223,7 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
NodeRef file1;
NodeRef file2;
NodeRef file3;
- Boolean result;
+ Set propertyValues;
@Override
public void given() throws Exception
@@ -179,13 +238,14 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
@Override
public void when() throws Exception
{
- result = queryDAO.hasChildrenWithPropertyValues(parentFolder, PROP_DESCRIPTION, Arrays.asList("descr1", "descr2", "descr3"));
+ propertyValues = queryDAO.getChildrenStringPropertyValues(parentFolder, PROP_DESCRIPTION);
+
}
@Override
public void then() throws Exception
{
- assertFalse(result);
+ assertTrue(propertyValues.isEmpty());
}
@Override
@@ -201,17 +261,17 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
/**
* Given a folder with no children but the property set on itself
- * When I check if the folder contains children having certain descriptions
- * Then the answer is negative
+ * When get the children property values
+ * Then the list is empty
*/
@org.junit.Test
- public void testHasChildrenWithPropertyValues_noChildren() throws Exception
+ public void testGetChildrenWithPropertyValues_noChildren() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
NodeRef folder;
String propValue = "descr";
- Boolean result;
+ Set propertyValues;
@Override
public void given() throws Exception
@@ -224,13 +284,13 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
@Override
public void when() throws Exception
{
- result = queryDAO.hasChildrenWithPropertyValues(folder, PROP_DESCRIPTION, Arrays.asList("descr"));
+ propertyValues = queryDAO.getChildrenStringPropertyValues(folder, PROP_DESCRIPTION);
}
@Override
public void then() throws Exception
{
- assertFalse(result);
+ assertTrue(propertyValues.isEmpty());
}
@Override
@@ -246,17 +306,17 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
/**
* Given a folder with children and an unused property
- * When I check if the folder contains children having the unused property
- * Then the answer is negative
+ * When I get the property values for the unused property
+ * Then empty list is returned
*/
@org.junit.Test
- public void testHasChildrenWithPropertyValues_propertyNotUsed() throws Exception
+ public void testGetChildrenWithPropertyValues_propertyNotUsed() throws Exception
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
NodeRef parentFolder;
QName property;
- Boolean result;
+ Set propertyValues;
@Override
public void given() throws Exception
@@ -271,13 +331,13 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
@Override
public void when() throws Exception
{
- result = queryDAO.hasChildrenWithPropertyValues(folder, property, Arrays.asList("descr"));
+ propertyValues = queryDAO.getChildrenStringPropertyValues(folder, property);
}
@Override
public void then() throws Exception
{
- assertFalse(result);
+ assertTrue(propertyValues.isEmpty());
}
@Override
@@ -291,50 +351,4 @@ public class RecordsManagementQueryDAOImplTest extends BaseRMTestCase implements
});
}
- /**
- * Given any folder and any property
- * When I pass an empty array to the hasChildrenWithPropertyValues method
- * Then the answer is negative
- */
- @org.junit.Test
- public void testHasChildrenWithPropertyValues_emptyArray() throws Exception
- {
- doBehaviourDrivenTest(new BehaviourDrivenTest()
- {
- NodeRef parentFolder;
- NodeRef file1;
- Boolean result;
-
- @Override
- public void given() throws Exception
- {
- setupCollaborationSiteTestDataImpl();
- parentFolder = fileFolderService.create(documentLibrary, GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
- file1 = fileFolderService.create(parentFolder, GUID.generate(), ContentModel.TYPE_FOLDER).getNodeRef();
-
- nodeService.setProperty(file1, PROP_DESCRIPTION, "descr1");
- }
-
- @Override
- public void when() throws Exception
- {
- result = queryDAO.hasChildrenWithPropertyValues(folder, PROP_DESCRIPTION, new ArrayList());
- }
-
- @Override
- public void then() throws Exception
- {
- assertFalse(result);
- }
-
- @Override
- public void after() throws Exception
- {
- if (folder != null && nodeService.exists(folder))
- {
- nodeService.deleteNode(folder);
- }
- }
- });
- }
}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
index 4eeb564b49..06dc185a44 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseRMTestCase.java
@@ -54,7 +54,6 @@ import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderServi
import org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService;
import org.alfresco.module.org_alfresco_module_rm.report.ReportService;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
-import org.alfresco.module.org_alfresco_module_rm.role.Role;
import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
import org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService;
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/action/impl/BroadcastDispositionActionDefinitionUpdateActionUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/action/impl/BroadcastDispositionActionDefinitionUpdateActionUnitTest.java
index b0129ba6ec..275ffe4f82 100644
--- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/action/impl/BroadcastDispositionActionDefinitionUpdateActionUnitTest.java
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/action/impl/BroadcastDispositionActionDefinitionUpdateActionUnitTest.java
@@ -102,7 +102,7 @@ public class BroadcastDispositionActionDefinitionUpdateActionUnitTest
when(mockAction.getName()).thenReturn("mockAction");
// Set up the disposition service to return a known "disposition as of" date.
Date asOfDate = new Date();
- when(mockDispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition, false))
+ when(mockDispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition))
.thenReturn(asOfDate);
// Call the method under test.
@@ -160,7 +160,7 @@ public class BroadcastDispositionActionDefinitionUpdateActionUnitTest
when(mockAction.getParameterValue(CHANGED_PROPERTIES)).thenReturn((Serializable) asList(PROP_DISPOSITION_PERIOD_PROPERTY));
// Set up the expected "as of" date.
Date newAsOfDate = new Date(123456789000L);
- when(mockDispositionService.calculateAsOfDate(recordNode, mockActionDefinition, false)).thenReturn(newAsOfDate);
+ when(mockDispositionService.calculateAsOfDate(recordNode, mockActionDefinition)).thenReturn(newAsOfDate);
// Call the method under test.
action.executeImpl(mockAction, definitionNode);
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImplUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImplUnitTest.java
new file mode 100644
index 0000000000..1e957087ce
--- /dev/null
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImplUnitTest.java
@@ -0,0 +1,200 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.audit;
+
+import static java.util.Collections.emptyList;
+
+import static org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService.ReportFormat.JSON;
+import static org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl.DOD5015_AUDIT_APPLICATION_NAME;
+import static org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl.RM_AUDIT_APPLICATION_NAME;
+import static org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditServiceImpl.RM_AUDIT_PATH_ROOT;
+import static org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model.TYPE_DOD_5015_SITE;
+import static org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService.DEFAULT_RM_SITE_ID;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.TYPE_RM_SITE;
+import static org.alfresco.module.org_alfresco_module_rm.model.rma.type.RmSiteType.DEFAULT_SITE_NAME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.google.common.collect.Sets;
+
+import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
+import org.alfresco.repo.audit.AuditComponent;
+import org.alfresco.service.cmr.audit.AuditQueryParameters;
+import org.alfresco.service.cmr.audit.AuditService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.site.SiteInfo;
+import org.alfresco.service.cmr.site.SiteService;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+/**
+ * Unit tests for {@link RecordsManagementAuditServiceImpl}.
+ *
+ * @author Tom Page
+ * @since 2.7
+ */
+public class RecordsManagementAuditServiceImplUnitTest
+{
+ /** The maximum entries to return in the audit query. */
+ private static final int MAX_ENTRIES = 10;
+ /** A node representing the file plan root. */
+ private static final NodeRef FILE_PLAN_NODE = new NodeRef("file://plan/node");
+ /** A node representing the RM site. */
+ private static final NodeRef RM_SITE_NODE = new NodeRef("rm://site/node");
+ /** The class under test. */
+ @InjectMocks
+ private RecordsManagementAuditServiceImpl recordsManagementAuditServiceImpl;
+ @Mock
+ private NodeService mockNodeService;
+ @Mock
+ private SiteService mockSiteService;
+ @Mock
+ private AuditService mockAuditService;
+ @Mock
+ private FilePlanService mockFilePlanService;
+ @Mock
+ AuditComponent mockAuditComponent;
+ @Mock
+ private Writer mockWriter;
+ @Mock
+ private SiteInfo mockSiteInfo;
+ @Captor
+ private ArgumentCaptor queryParamsCaptor;
+
+ /** Set up the mocks. */
+ @Before
+ public void setUp()
+ {
+ initMocks(this);
+
+ when(mockFilePlanService.getFilePlanBySiteId(DEFAULT_RM_SITE_ID)).thenReturn(FILE_PLAN_NODE);
+ when(mockSiteService.getSite(DEFAULT_SITE_NAME)).thenReturn(mockSiteInfo);
+ when(mockSiteInfo.getNodeRef()).thenReturn(RM_SITE_NODE);
+
+ recordsManagementAuditServiceImpl.setIgnoredAuditProperties(emptyList());
+ }
+
+ /**
+ * Check that if the RM site is not a DOD site then the audit trail doesn't make a query for DOD events.
+ *
+ * @throws IOException Unexpected.
+ */
+ @Test
+ public void testAuditWithoutDOD() throws IOException
+ {
+ RecordsManagementAuditQueryParameters params = new RecordsManagementAuditQueryParameters();
+ params.setMaxEntries(MAX_ENTRIES);
+ List results = new ArrayList<>();
+ // Return a standard site type.
+ when(mockNodeService.getType(RM_SITE_NODE)).thenReturn(TYPE_RM_SITE);
+
+ // Call the method under test.
+ recordsManagementAuditServiceImpl.getAuditTrailImpl(params, results, mockWriter, JSON);
+
+ // Check that exactly one audit query was performed.
+ verify(mockAuditService, times(1))
+ .auditQuery(any(AuditService.AuditQueryCallback.class), queryParamsCaptor.capture(),
+ eq(MAX_ENTRIES));
+ // We always need to make the standard query - regardless of the type of RM site (to get events like RM site created).
+ assertEquals("The application name should be the standard RM application", RM_AUDIT_APPLICATION_NAME,
+ queryParamsCaptor.getValue().getApplicationName());
+ // Check that the event of viewing the audit log was itself audited.
+ verify(mockAuditComponent).recordAuditValues(eq(RM_AUDIT_PATH_ROOT), any(Map.class));
+ }
+
+ /**
+ * Check that if the RM site is a DOD site then the audit trail makes a query for DOD events and the standard events.
+ *
+ * @throws IOException Unexpected.
+ */
+ @Test
+ public void testAuditWithDOD() throws IOException
+ {
+ RecordsManagementAuditQueryParameters params = new RecordsManagementAuditQueryParameters();
+ params.setMaxEntries(MAX_ENTRIES);
+ List results = new ArrayList<>();
+ // Return a DOD site type.
+ when(mockNodeService.getType(RM_SITE_NODE)).thenReturn(TYPE_DOD_5015_SITE);
+
+ // Call the method under test.
+ recordsManagementAuditServiceImpl.getAuditTrailImpl(params, results, mockWriter, JSON);
+
+ // Check that two audit queries were performed (one for DOD events and one for standard events).
+ verify(mockAuditService, times(2))
+ .auditQuery(any(AuditService.AuditQueryCallback.class), queryParamsCaptor.capture(),
+ eq(MAX_ENTRIES));
+ Set apps = queryParamsCaptor.getAllValues().stream().map(AuditQueryParameters::getApplicationName)
+ .collect(Collectors.toSet());
+ // We always need to make the standard query - regardless of the type of RM site (to get events like RM site created).
+ assertEquals("Expected the standard audit query and the DOD audit query.",
+ Sets.newHashSet(RM_AUDIT_APPLICATION_NAME, DOD5015_AUDIT_APPLICATION_NAME), apps);
+ // Check that the event of viewing the audit log was itself audited.
+ verify(mockAuditComponent).recordAuditValues(eq(RM_AUDIT_PATH_ROOT), any(Map.class));
+ }
+
+ /** Check that passing null to getStartOfDay doesn't result in null being returned. */
+ @Test
+ public void testGetStartOfDay_null()
+ {
+ Date startOfDay = recordsManagementAuditServiceImpl.getStartOfDay(null);
+ assertNotNull("Expected date to be created by method.", startOfDay);
+ }
+
+ /** Check that any time component passed to getStartOfDay is not included in the response. */
+ @Test
+ public void testGetStartOfDay_timeDiscarded() throws Exception
+ {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
+ Date date = format.parse("2001-02-03 04:05:06.789");
+
+ // Call the method under test.
+ Date startOfDay = recordsManagementAuditServiceImpl.getStartOfDay(date);
+
+ assertEquals("Unexpected date truncation.", format.parse("2001-02-03 00:00:00.000"), startOfDay);
+ }
+}
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImplUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImplUnitTest.java
index 8ba2f1ac61..99d61053ec 100644
--- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImplUnitTest.java
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImplUnitTest.java
@@ -82,7 +82,7 @@ public class DispositionServiceImplUnitTest
when(mockPeriod.getNextDate(createdDate)).thenReturn(nextDate);
// Call the method under test.
- Date asOfDate = dispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition, true);
+ Date asOfDate = dispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition);
assertEquals("Unexpected calculation for 'as of' date", nextDate, asOfDate);
}
@@ -95,7 +95,7 @@ public class DispositionServiceImplUnitTest
when(mockDispositionActionDefinition.getPeriod()).thenReturn(null);
// Call the method under test.
- Date asOfDate = dispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition, true);
+ Date asOfDate = dispositionService.calculateAsOfDate(CONTENT_NODE_REF, mockDispositionActionDefinition);
assertNull("It should not be possible to determine the 'as of' date.", asOfDate);
}
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/email/RFC822MetadataExtracterUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/email/RFC822MetadataExtracterUnitTest.java
new file mode 100644
index 0000000000..7aca0c6679
--- /dev/null
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/email/RFC822MetadataExtracterUnitTest.java
@@ -0,0 +1,169 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.email;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model;
+import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.namespace.QName;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+
+/**
+ * Unit test for RFC822MetadataExtracter
+ *
+ * @author Ana Manolache
+ * @since 2.7
+ */
+public class RFC822MetadataExtracterUnitTest extends BaseUnitTest
+{
+ @InjectMocks
+ private RFC822MetadataExtracter metadataExtracter;
+
+ private static final Map COMMON_PROPERTIES = ImmutableMap.of(
+ ContentModel.PROP_NAME, "Name",
+ ContentModel.PROP_TITLE, "Title");
+ private static final Map RECORD_PROPERTIES = ImmutableMap.of(
+ RecordsManagementModel.PROP_DECLARED_BY, "DeclaredBy",
+ RecordsManagementModel.PROP_DECLARED_AT, new Date());
+ private static final Map DOD_PROPERTIES = ImmutableMap.of(
+ DOD5015Model.PROP_ORIGINATOR, "DODOriginator",
+ DOD5015Model.PROP_ADDRESS, "Title");
+
+ /**
+ * Given a node that is not a record nor a dod record
+ * and has record and dod record properties
+ * When the method is called
+ * Then the record properties and dod properties are filtered out
+ */
+ @Test
+ public void testRemoveSensitivePropertiesFromCommonNodes()
+ {
+ // Given
+ NodeRef node = generateNodeRef();
+ when(mockedNodeService.hasAspect(node, RecordsManagementModel.ASPECT_RECORD)).thenReturn(false);
+ when(mockedNodeService.hasAspect(node, DOD5015Model.ASPECT_DOD_5015_RECORD)).thenReturn(false);
+
+ // When
+ Map systemProperties = new HashMap<>(COMMON_PROPERTIES);
+ systemProperties.putAll(RECORD_PROPERTIES);
+ systemProperties.putAll(DOD_PROPERTIES);
+ metadataExtracter.filterSystemProperties(systemProperties, generateTargetProperties(node));
+
+ // Then
+ assertTrue("Sensitive properties were not properly filtered out.",
+ systemProperties.keySet().equals(COMMON_PROPERTIES.keySet()));
+ }
+
+ /**
+ * Given a node that is a record
+ * and has record properties and dod properties
+ * When the method is called
+ * Then the DOD properties are filtered out
+ * and common and record properties are preserved
+ */
+ @Test
+ public void testRemoveDodPropertiesFromRecordNodes()
+ {
+ // Given
+ NodeRef node = generateNodeRef();
+ when(mockedNodeService.hasAspect(node, RecordsManagementModel.ASPECT_RECORD)).thenReturn(true);
+ when(mockedNodeService.hasAspect(node, DOD5015Model.ASPECT_DOD_5015_RECORD)).thenReturn(false);
+
+ // When
+ Map systemProperties = new HashMap<>(COMMON_PROPERTIES);
+ systemProperties.putAll(RECORD_PROPERTIES);
+ systemProperties.putAll(DOD_PROPERTIES);
+ metadataExtracter.filterSystemProperties(systemProperties, generateTargetProperties(node));
+
+ // Then
+ assertTrue("Common properties should not be filtered out from record nodes.",
+ systemProperties.keySet().containsAll(COMMON_PROPERTIES.keySet()));
+ assertTrue("Record properties should not be filtered out from record nodes.",
+ systemProperties.keySet().containsAll(RECORD_PROPERTIES.keySet()));
+ assertFalse("Sensitive DOD properties were not properly filtered out from record nodes.",
+ systemProperties.keySet().removeAll(DOD_PROPERTIES.keySet()));
+ }
+
+ /**
+ * Given a node that is a dod record
+ * and has record properties and dod properties
+ * When the method is called
+ * Then the record properties are filtered out
+ * and common and DOD properties are preserved
+ */
+ @Test
+ public void testRemoveRecordPropertiesFromDodNodes()
+ {
+ // Given
+ NodeRef node = generateNodeRef();
+ when(mockedNodeService.hasAspect(node, RecordsManagementModel.ASPECT_RECORD)).thenReturn(false);
+ when(mockedNodeService.hasAspect(node, DOD5015Model.ASPECT_DOD_5015_RECORD)).thenReturn(true);
+
+ // When
+ Map systemProperties = new HashMap<>(COMMON_PROPERTIES);
+ systemProperties.putAll(RECORD_PROPERTIES);
+ systemProperties.putAll(DOD_PROPERTIES);
+ metadataExtracter.filterSystemProperties(systemProperties, generateTargetProperties(node));
+
+ // Then
+ assertTrue("Common properties should not be filtered out from DOD nodes.",
+ systemProperties.keySet().containsAll(COMMON_PROPERTIES.keySet()));
+ assertTrue("DOD properties should not be filtered out from DOD nodes.",
+ systemProperties.keySet().containsAll(DOD_PROPERTIES.keySet()));
+ assertFalse("Sensitive record properties were not properly filtered out from DOD nodes.",
+ systemProperties.keySet().removeAll(RECORD_PROPERTIES.keySet()));
+ }
+
+ /**
+ * Helper method that generates target properties such as the given node is retrieved from them
+ *
+ * @param node the node to represent in the properties
+ * @return the list of properties containing the node's information
+ */
+ private Map generateTargetProperties(NodeRef node)
+ {
+ Map targetProperties = new HashMap<>();
+ targetProperties.put(ContentModel.PROP_STORE_PROTOCOL, node.getStoreRef().getProtocol());
+ targetProperties.put(ContentModel.PROP_STORE_IDENTIFIER, node.getStoreRef().getIdentifier());
+ targetProperties.put(ContentModel.PROP_NODE_UUID, node.getId());
+ return targetProperties;
+ }
+}
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspectUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspectUnitTest.java
index 730da904f3..1c14788f89 100644
--- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspectUnitTest.java
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/RecordAspectUnitTest.java
@@ -30,8 +30,6 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_RECORD;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -39,11 +37,8 @@ import static org.mockito.MockitoAnnotations.initMocks;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
-import org.alfresco.repo.policy.BehaviourFilter;
+import org.alfresco.module.org_alfresco_module_rm.util.ContentBinDuplicationUtility;
import org.alfresco.service.cmr.repository.AssociationRef;
-import org.alfresco.service.cmr.repository.ContentReader;
-import org.alfresco.service.cmr.repository.ContentService;
-import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.junit.Before;
@@ -70,15 +65,9 @@ public class RecordAspectUnitTest
@Mock
private NodeService mockNodeService;
@Mock
- private BehaviourFilter mockBehaviorFilter;
- @Mock
- private ContentService mockContentService;
- @Mock
- private ContentReader mockContentReader;
- @Mock
- private ContentWriter mockContentWriter;
- @Mock
private ExtendedSecurityService mockExtendedSecurityService;
+ @Mock
+ private ContentBinDuplicationUtility mockContentBinDuplicationUtility;
@Before
public void setUp()
@@ -91,12 +80,10 @@ public class RecordAspectUnitTest
public void testDuplicateBinBeforeAddingAspectForFileWithCopy()
{
when(mockNodeService.getSourceAssocs(NODE_REF, ContentModel.ASSOC_ORIGINAL)).thenReturn(asList(SOURCE_ASSOC_REF));
- when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
- when(mockContentService.getWriter(NODE_REF, ContentModel.PROP_CONTENT, true)).thenReturn(mockContentWriter);
recordAspect.beforeAddAspect(NODE_REF, ASPECT_RECORD);
- verifyBeforeAddAspectMethodsInvocations(1);
+ verify(mockContentBinDuplicationUtility, times(1)).duplicate(NODE_REF);
}
/** Check that the bin is duplicated before adding the aspect if the file is a copy. */
@@ -104,29 +91,10 @@ public class RecordAspectUnitTest
public void testDuplicateBinBeforeAddingAspectForCopy()
{
when(mockNodeService.getTargetAssocs(NODE_REF, ContentModel.ASSOC_ORIGINAL)).thenReturn(asList(TARGET_ASSOC_REF));
- when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
- when(mockContentService.getWriter(NODE_REF, ContentModel.PROP_CONTENT, true)).thenReturn(mockContentWriter);
recordAspect.beforeAddAspect(NODE_REF, ASPECT_RECORD);
- verifyBeforeAddAspectMethodsInvocations(1);
- }
-
- /** Check that no content bin is created if the file does not have content. */
- @Test
- public void testBeforeAddAspectOnFileWithNoContent()
- {
- when(mockNodeService.getTargetAssocs(NODE_REF, ContentModel.ASSOC_ORIGINAL)).thenReturn(asList(TARGET_ASSOC_REF));
- when(mockContentService.getReader(NODE_REF, ContentModel.PROP_CONTENT)).thenReturn(null);
-
- recordAspect.beforeAddAspect(NODE_REF, ASPECT_RECORD);
-
- verify(mockBehaviorFilter, times(1)).disableBehaviour(eq(ContentModel.ASPECT_AUDITABLE));
- verify(mockBehaviorFilter, times(1)).disableBehaviour(eq(ContentModel.ASPECT_VERSIONABLE));
- verify(mockContentService, times(1)).getReader(NODE_REF, ContentModel.PROP_CONTENT);
- verify(mockContentService, never()).getWriter(NODE_REF, ContentModel.PROP_CONTENT, true);
- verify(mockBehaviorFilter, times(1)).enableBehaviour(eq(ContentModel.ASPECT_AUDITABLE));
- verify(mockBehaviorFilter, times(1)).enableBehaviour(eq(ContentModel.ASPECT_VERSIONABLE));
+ verify(mockContentBinDuplicationUtility, times(1)).duplicate(NODE_REF);
}
/** Check that the bin is not duplicated before adding the aspect if the node has no copies. */
@@ -138,7 +106,7 @@ public class RecordAspectUnitTest
recordAspect.beforeAddAspect(NODE_REF, ASPECT_RECORD);
- verifyBeforeAddAspectMethodsInvocations(0);
+ verify(mockContentBinDuplicationUtility, times(0)).duplicate(NODE_REF);
}
/** Check that the bin is duplicated when copying a record. */
@@ -147,30 +115,10 @@ public class RecordAspectUnitTest
{
when(mockNodeService.exists(COPY_REF)).thenReturn(true);
when(mockNodeService.hasAspect(COPY_REF, ASPECT_RECORD)).thenReturn(true);
- when(mockContentService.getReader(COPY_REF, ContentModel.PROP_CONTENT)).thenReturn(mockContentReader);
- when(mockContentService.getWriter(COPY_REF, ContentModel.PROP_CONTENT, true)).thenReturn(mockContentWriter);
recordAspect.onCopyComplete(null, NODE_REF, COPY_REF, true, null);
verify(mockExtendedSecurityService, times(1)).remove(COPY_REF);
- verify(mockContentService, times(1)).getReader(COPY_REF, ContentModel.PROP_CONTENT);
- verify(mockContentService, times(1)).getWriter(COPY_REF, ContentModel.PROP_CONTENT, true);
- verify(mockContentWriter, times(1)).putContent(mockContentReader);
- }
-
- /**
- * Helper to verify beforeAddAspect methods invocations
- *
- * @param wantedNumberOfInvocations wanted number of invocations for each method
- */
- private void verifyBeforeAddAspectMethodsInvocations(int wantedNumberOfInvocations)
- {
- verify(mockBehaviorFilter, times(wantedNumberOfInvocations)).disableBehaviour(eq(ContentModel.ASPECT_AUDITABLE));
- verify(mockBehaviorFilter, times(wantedNumberOfInvocations)).disableBehaviour(eq(ContentModel.ASPECT_VERSIONABLE));
- verify(mockContentService, times(wantedNumberOfInvocations)).getReader(NODE_REF, ContentModel.PROP_CONTENT);
- verify(mockContentService, times(wantedNumberOfInvocations)).getWriter(NODE_REF, ContentModel.PROP_CONTENT, true);
- verify(mockContentWriter, times(wantedNumberOfInvocations)).putContent(mockContentReader);
- verify(mockBehaviorFilter, times(wantedNumberOfInvocations)).enableBehaviour(eq(ContentModel.ASPECT_AUDITABLE));
- verify(mockBehaviorFilter, times(wantedNumberOfInvocations)).enableBehaviour(eq(ContentModel.ASPECT_VERSIONABLE));
+ verify(mockContentBinDuplicationUtility, times(1)).duplicate(COPY_REF);
}
}
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/ClassificationReasonsUtilUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/ClassificationReasonsUtilUnitTest.java
new file mode 100644
index 0000000000..0f46199e00
--- /dev/null
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/ClassificationReasonsUtilUnitTest.java
@@ -0,0 +1,128 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+package org.alfresco.module.org_alfresco_module_rm.script.slingshot;
+
+import static org.alfresco.model.ContentModel.ASSOC_CHILDREN;
+import static org.alfresco.model.ContentModel.PROP_NAME;
+import static org.alfresco.module.org_alfresco_module_rm.script.slingshot.ClassificationReasonsUtil.CLASSIFICATION_REASONS_CONTAINER;
+import static org.alfresco.module.org_alfresco_module_rm.script.slingshot.ClassificationReasonsUtil.PROP_CLASSIFICATION_REASON_CODE;
+import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.namespace.QName;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * @author Ross Gale
+ * @since 2.7
+ */
+public class ClassificationReasonsUtilUnitTest
+{
+
+ @Mock
+ private NodeService nodeService;
+
+ @Mock
+ private ChildAssociationRef childAssociationRef;
+
+ @Mock
+ private ChildAssociationRef reason;
+
+ @Mock
+ private Map properties;
+
+ @InjectMocks
+ private ClassificationReasonsUtil classificationReasonsUtil;
+
+ private NodeRef childNodeRef;
+
+ @Before
+ public void setUp()
+ {
+ MockitoAnnotations.initMocks(this);
+ NodeRef rootNodeRef = new NodeRef("workspace://SpacesStore/rootNodeRef");
+ NodeRef containerNodeRef = new NodeRef("workspace://SpacesStore/containerNodeRef");
+ childNodeRef = new NodeRef("workspace://SpacesStore/childNodeRef");
+ List assocRefs = new ArrayList<>();
+ List childAssocRefs = new ArrayList<>();
+ assocRefs.add(childAssociationRef);
+ childAssocRefs.add(reason);
+ when(reason.getChildRef()).thenReturn(childNodeRef);
+ when(nodeService.getRootNode(STORE_REF_WORKSPACE_SPACESSTORE)).thenReturn(rootNodeRef);
+ when(nodeService.getChildAssocs(rootNodeRef, ASSOC_CHILDREN, CLASSIFICATION_REASONS_CONTAINER)).thenReturn(assocRefs);
+ when(childAssociationRef.getChildRef()).thenReturn(containerNodeRef);
+ when(nodeService.getChildAssocs(containerNodeRef)).thenReturn(childAssocRefs);
+ }
+
+ /**
+ * Check no modifications are made to non matching parts of the query string
+ */
+ @Test
+ public void testNoChangeMadeToStringIfKeyNotFound()
+ {
+ String stringToTest = "noChangeMadeToString";
+ assertEquals("Change made to string",stringToTest, classificationReasonsUtil.replaceReasonWithNodeRef(stringToTest).trim());
+ }
+
+ /**
+ * Check no modifications made if the plain text parameter doesn't have a stored match
+ */
+ @Test
+ public void testNoChangeMadeToStringIfMatchNotFound()
+ {
+ when(nodeService.getProperties(childNodeRef)).thenReturn(properties);
+ when(properties.get(PROP_CLASSIFICATION_REASON_CODE)).thenReturn("not a match!");
+ String stringToTest = "clf:classificationReasons:noChangeMadeToString";
+ assertEquals("Change made to string", stringToTest, classificationReasonsUtil.replaceReasonWithNodeRef(stringToTest).trim());
+ }
+
+ /**
+ * Check the query is updated correctly when a match is found
+ */
+ @Test
+ public void testChangeMadeToStringIfMatchFound()
+ {
+ when(nodeService.getProperties(childNodeRef)).thenReturn(properties);
+ when(properties.get(PROP_CLASSIFICATION_REASON_CODE)).thenReturn("stringToChange");
+ when(properties.get(PROP_NAME)).thenReturn("newString");
+ String stringToTest = "clf:classificationReasons:stringToChange";
+ assertEquals("No change made to string", "clf:classificationReasons:newString", classificationReasonsUtil.replaceReasonWithNodeRef(stringToTest).trim());
+ }
+}
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RecordCategoryUtilUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RecordCategoryUtilUnitTest.java
new file mode 100644
index 0000000000..6d2e505125
--- /dev/null
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RecordCategoryUtilUnitTest.java
@@ -0,0 +1,132 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2019 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.script.slingshot;
+
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.PROP_IDENTIFIER;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.TYPE_NON_ELECTRONIC_DOCUMENT;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.TYPE_RECORD_CATEGORY;
+import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.TYPE_RECORD_FOLDER;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.when;
+
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.Path;
+import org.alfresco.service.cmr.repository.Path.ChildAssocElement;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for methods in the RecordsCategoryUtil class
+ *
+ * @author Ross Gale
+ * @since 2.7
+ */
+public class RecordCategoryUtilUnitTest
+{
+ @Mock
+ private NodeService nodeService;
+
+ @Mock
+ private ChildAssocElement element;
+
+ @Mock
+ private ChildAssociationRef childAssociationRef;
+
+ @InjectMocks
+ private RecordCategoryUtil recordCategoryUtil;
+
+ private Path path;
+
+ private NodeRef recordNodeRef;
+
+ private NodeRef recordFolderNodeRef;
+
+ private NodeRef categoryNodeRef;
+
+ @Before
+ public void setUp()
+ {
+ MockitoAnnotations.initMocks(this);
+ recordNodeRef = new NodeRef("test://recordNode/");
+ recordFolderNodeRef = new NodeRef("test://recordFolderNode/");
+ categoryNodeRef = new NodeRef("test://categoryNode/");
+ path = new Path();
+ path.append(element);
+ when(nodeService.getType(recordFolderNodeRef)).thenReturn(TYPE_RECORD_FOLDER);
+ when(nodeService.getType(recordNodeRef)).thenReturn(TYPE_NON_ELECTRONIC_DOCUMENT);
+ when(nodeService.getPath(recordNodeRef)).thenReturn(path);
+ when(nodeService.getPath(recordFolderNodeRef)).thenReturn(path);
+ when(element.getRef()).thenReturn(childAssociationRef);
+ when(childAssociationRef.getChildRef()).thenReturn(categoryNodeRef);
+ when(nodeService.getType(categoryNodeRef)).thenReturn(TYPE_RECORD_CATEGORY);
+ when(nodeService.getProperty(categoryNodeRef, PROP_IDENTIFIER)).thenReturn("RecordCategoryId");
+ }
+
+ /**
+ * Tests an id is returned from a valid node ref
+ */
+ @Test
+ public void testGetIdFromNodeRef()
+ {
+ assertEquals("RecordCategoryId",recordCategoryUtil.getCategoryIdFromNodeId(recordNodeRef,false));
+ }
+
+ /**
+ * Tests an id can be returned for a non record with the correct option selected
+ */
+ @Test
+ public void testGetIdFromNodeRefReturnsForNonRecordWhenOptionSelected()
+ {
+ assertEquals("RecordCategoryId", recordCategoryUtil.getCategoryIdFromNodeId(recordFolderNodeRef, true));
+ }
+
+ /**
+ * Tests no id is returned for a folder if option isn't selected
+ */
+ @Test
+ public void testGetIdFromNodeRefReturnsNullForNonRecordWhenOptionSelected()
+ {
+ assertNull(recordCategoryUtil.getCategoryIdFromNodeId(recordFolderNodeRef,false));
+ }
+
+ /**
+ * Tests no id is returned when a categories isn't found on the path
+ */
+ @Test
+ public void testGetIdFromNodeRefReturnsNullWithNoCategory()
+ {
+ when(nodeService.getPath(recordNodeRef)).thenReturn(new Path());
+ assertNull(recordCategoryUtil.getCategoryIdFromNodeId(recordNodeRef, false));
+ }
+}
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/MockAuthenticationUtilHelper.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/MockAuthenticationUtilHelper.java
index 8785ca8daf..73b31c79bd 100644
--- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/MockAuthenticationUtilHelper.java
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/MockAuthenticationUtilHelper.java
@@ -45,6 +45,10 @@ import org.mockito.stubbing.Answer;
*/
public class MockAuthenticationUtilHelper
{
+ public static final String SYSTEM_USER = "system";
+ public static final String ADMIN_USER = "admin";
+ public static final String GUEST_USER = "guest";
+
/**
* Set up a Mockito mock AuthenticationUtil so that it executes all methods assuming the user has
* permissions. If the mock is asked for details about the user then it assumes the currently authenticated user is
@@ -95,10 +99,10 @@ public class MockAuthenticationUtilHelper
}).when(mockAuthenticationUtil).