mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	Compare commits
	
		
			80 Commits
		
	
	
		
			17.79
			...
			hack/hacka
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					cd8ef77b3e | ||
| 
						 | 
					8622e0e102 | ||
| 
						 | 
					69170dde35 | ||
| 
						 | 
					c848024130 | ||
| 
						 | 
					553f78bb1e | ||
| 
						 | 
					9a3ceb21a8 | ||
| 
						 | 
					57d0ff62dc | ||
| 
						 | 
					42bd94c1da | ||
| 
						 | 
					c5dd6538f8 | ||
| 
						 | 
					152c036d86 | ||
| 
						 | 
					f2055f91dc | ||
| 
						 | 
					a1d7f0d479 | ||
| 
						 | 
					8476f01b35 | ||
| 
						 | 
					6c4b9e458a | ||
| 
						 | 
					0f99dec012 | ||
| 
						 | 
					06c7836e70 | ||
| 
						 | 
					2ceb7384bf | ||
| 
						 | 
					d848c83a57 | ||
| 
						 | 
					be7572a978 | ||
| 
						 | 
					ef45aaf9cc | ||
| 
						 | 
					6f834909f6 | ||
| 
						 | 
					b928598bd7 | ||
| 
						 | 
					678eeab278 | ||
| 
						 | 
					45f9bd6569 | ||
| 
						 | 
					23b8c0e7a6 | ||
| 
						 | 
					9c98f7b0fb | ||
| 
						 | 
					6e1d5c81e2 | ||
| 
						 | 
					092d895f6a | ||
| 
						 | 
					a568c87571 | ||
| 
						 | 
					3aac7be11c | ||
| 
						 | 
					700fbce572 | ||
| 
						 | 
					7be96e788b | ||
| 
						 | 
					0af001be2a | ||
| 
						 | 
					f38a36910f | ||
| 
						 | 
					972f81ab8b | ||
| 
						 | 
					1bd0dfd114 | ||
| 
						 | 
					775de0e94c | ||
| 
						 | 
					78d2ed247a | ||
| 
						 | 
					5ca3630398 | ||
| 
						 | 
					ee7383dcab | ||
| 
						 | 
					36b3dc25c0 | ||
| 
						 | 
					0b94042b6f | ||
| 
						 | 
					27d3701c8b | ||
| 
						 | 
					dc0102001f | ||
| 
						 | 
					12bc363bcd | ||
| 
						 | 
					2ab89f0d79 | ||
| 
						 | 
					807e509859 | ||
| 
						 | 
					403da286e8 | ||
| 
						 | 
					cc3f8aaff4 | ||
| 
						 | 
					be925ab67d | ||
| 
						 | 
					de4ac000dd | ||
| 
						 | 
					b2b866e0f9 | ||
| 
						 | 
					984bc151af | ||
| 
						 | 
					b057455cde | ||
| 
						 | 
					40edaccd1a | ||
| 
						 | 
					a802a17d92 | ||
| 
						 | 
					332626421b | ||
| 
						 | 
					1baf8d6fae | ||
| 
						 | 
					4bae0f2060 | ||
| 
						 | 
					0c017ac30c | ||
| 
						 | 
					cc0940e519 | ||
| 
						 | 
					0190b9060a | ||
| 
						 | 
					596e964553 | ||
| 
						 | 
					5d22e161d7 | ||
| 
						 | 
					bb27430f6a | ||
| 
						 | 
					1af879a7ed | ||
| 
						 | 
					c029f5afa3 | ||
| 
						 | 
					3b93814d76 | ||
| 
						 | 
					656ecdc41d | ||
| 
						 | 
					8150abf8b7 | ||
| 
						 | 
					cab6fd6d2c | ||
| 
						 | 
					e45211ad0f | ||
| 
						 | 
					414cba0c1a | ||
| 
						 | 
					75b74a5d77 | ||
| 
						 | 
					d3efea8873 | ||
| 
						 | 
					6c407b1ef5 | ||
| 
						 | 
					f7dcbc6551 | ||
| 
						 | 
					ed1ee00cee | ||
| 
						 | 
					bba1664fef | ||
| 
						 | 
					d675d58929 | 
							
								
								
									
										11
									
								
								.github/workflows/hackathon.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.github/workflows/hackathon.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
name: Hackathon
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  sleep:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v3
 | 
			
		||||
      - run: sleep 240
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-community-repo-amps</artifactId>
 | 
			
		||||
      <version>17.79</version>
 | 
			
		||||
      <version>17.102-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-governance-services-community-parent</artifactId>
 | 
			
		||||
      <version>17.79</version>
 | 
			
		||||
      <version>17.102-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-governance-services-automation-community-repo</artifactId>
 | 
			
		||||
      <version>17.79</version>
 | 
			
		||||
      <version>17.102-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <build>
 | 
			
		||||
@@ -45,7 +45,7 @@
 | 
			
		||||
      <dependency>
 | 
			
		||||
         <groupId>org.slf4j</groupId>
 | 
			
		||||
         <artifactId>slf4j-reload4j</artifactId>
 | 
			
		||||
         <version>1.7.35</version>
 | 
			
		||||
         <version>${dependency.slf4j.version}</version>
 | 
			
		||||
         <scope>test</scope>
 | 
			
		||||
      </dependency>
 | 
			
		||||
      <dependency>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-governance-services-community-parent</artifactId>
 | 
			
		||||
      <version>17.79</version>
 | 
			
		||||
      <version>17.102-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-governance-services-community-repo-parent</artifactId>
 | 
			
		||||
      <version>17.79</version>
 | 
			
		||||
      <version>17.102-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <properties>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-governance-services-community-repo-parent</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <build>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-amps</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2005 - 2020 Alfresco Software Limited.
 | 
			
		||||
 * Copyright 2005 - 2022 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.
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
   <parent>
 | 
			
		||||
      <groupId>org.alfresco</groupId>
 | 
			
		||||
      <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
      <version>17.79</version>
 | 
			
		||||
      <version>17.102-SNAPSHOT</version>
 | 
			
		||||
   </parent>
 | 
			
		||||
 | 
			
		||||
   <dependencies>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <dependencies>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,6 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-packaging</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
</project>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-packaging</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-packaging</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <modules>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -27,9 +27,11 @@ package org.alfresco.rest.rules;
 | 
			
		||||
 | 
			
		||||
import static java.util.stream.Collectors.toList;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.createActionModel;
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
 | 
			
		||||
import static org.alfresco.utility.constants.UserRole.*;
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.*;
 | 
			
		||||
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
 | 
			
		||||
import static org.alfresco.utility.constants.UserRole.SiteConsumer;
 | 
			
		||||
import static org.alfresco.utility.constants.UserRole.SiteContributor;
 | 
			
		||||
import static org.alfresco.utility.constants.UserRole.SiteManager;
 | 
			
		||||
import static org.alfresco.utility.model.FileModel.getRandomFileModel;
 | 
			
		||||
import static org.alfresco.utility.model.FileType.TEXT_PLAIN;
 | 
			
		||||
import static org.alfresco.utility.report.log.Step.STEP;
 | 
			
		||||
@@ -39,10 +41,14 @@ import static org.springframework.http.HttpStatus.CREATED;
 | 
			
		||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
 | 
			
		||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.stream.IntStream;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.RestTest;
 | 
			
		||||
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleModel;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleModelsCollection;
 | 
			
		||||
import org.alfresco.utility.constants.UserRole;
 | 
			
		||||
@@ -60,6 +66,8 @@ import org.testng.annotations.Test;
 | 
			
		||||
@Test(groups = {TestGroup.RULES})
 | 
			
		||||
public class CreateRulesTests extends RestTest
 | 
			
		||||
{
 | 
			
		||||
    private static final String IGNORE_ID = "id";
 | 
			
		||||
    private static final String IGNORE_IS_SHARED = "isShared";
 | 
			
		||||
    private UserModel user;
 | 
			
		||||
    private SiteModel site;
 | 
			
		||||
    private FolderModel ruleFolder;
 | 
			
		||||
@@ -72,18 +80,26 @@ public class CreateRulesTests extends RestTest
 | 
			
		||||
        ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can create a rule. */
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can create a rule.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Also check that the isShared field is not returned when not requested.
 | 
			
		||||
     */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void createRule()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel("ruleName");
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModelWithModifiedValues();
 | 
			
		||||
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
                                       .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        RestRuleModel expectedRuleModel = createRuleModelWithModifiedValues();
 | 
			
		||||
        expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
 | 
			
		||||
        expectedRuleModel.setConditions(createEmptyConditionModel());
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().field("id").isNotNull()
 | 
			
		||||
            .assertThat().field("name").is("ruleName");
 | 
			
		||||
        rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
 | 
			
		||||
                .assertThat().field("id").isNotNull()
 | 
			
		||||
                .assertThat().field("isShared").isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check creating a rule in a non-existent folder returns an error. */
 | 
			
		||||
@@ -121,8 +137,7 @@ public class CreateRulesTests extends RestTest
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void createRuleWithEmptyName()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = new RestRuleModel();
 | 
			
		||||
        ruleModel.setName("");
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel("");
 | 
			
		||||
 | 
			
		||||
        restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
@@ -241,7 +256,7 @@ public class CreateRulesTests extends RestTest
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Try to create a three rules but the middle one has an error.");
 | 
			
		||||
        RestRuleModel ruleA = createRuleModel("ruleA");
 | 
			
		||||
        RestRuleModel ruleB = new RestRuleModel();
 | 
			
		||||
        RestRuleModel ruleB = createRuleModel("");
 | 
			
		||||
        // Don't set a name for Rule B.
 | 
			
		||||
        RestRuleModel ruleC = createRuleModel("ruleC");
 | 
			
		||||
        List<RestRuleModel> ruleModels = List.of(ruleA, ruleB, ruleC);
 | 
			
		||||
@@ -252,6 +267,85 @@ public class CreateRulesTests extends RestTest
 | 
			
		||||
        restClient.assertLastError().containsSummary("Rule name is a mandatory parameter");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can create a rule without description. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void createRuleWithoutDescription()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        UserModel admin = dataUser.getAdminUser();
 | 
			
		||||
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
            .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().field("id").isNotNull()
 | 
			
		||||
            .assertThat().field("name").is(RULE_NAME_DEFAULT)
 | 
			
		||||
            .assertThat().field("description").isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can create a rule without specifying triggers but with the default "inbound" value. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void createRuleWithoutTriggers()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        UserModel admin = dataUser.getAdminUser();
 | 
			
		||||
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
            .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().field("id").isNotNull()
 | 
			
		||||
            .assertThat().field("name").is(RULE_NAME_DEFAULT)
 | 
			
		||||
            .assertThat().field("triggers").is(List.of("inbound"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can create a rule without error script. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void createRuleWithoutErrorScript()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        UserModel admin = dataUser.getAdminUser();
 | 
			
		||||
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
            .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().field("id").isNotNull()
 | 
			
		||||
            .assertThat().field("name").is(RULE_NAME_DEFAULT)
 | 
			
		||||
            .assertThat().field("errorScript").isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can create a rule with irrelevant isShared flag, and it doesn't have impact to the process. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void createRuleWithSharedFlag()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        ruleModel.setIsShared(true);
 | 
			
		||||
        UserModel admin = dataUser.getAdminUser();
 | 
			
		||||
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
            .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().field("id").isNotNull()
 | 
			
		||||
            .assertThat().field("name").is(RULE_NAME_DEFAULT)
 | 
			
		||||
            .assertThat().field("isShared").isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can create a rule. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void createRuleAndIncludeFieldsInResponse()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel("ruleName");
 | 
			
		||||
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
                                       .include("isShared")
 | 
			
		||||
                                       .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().field("isShared").isNotNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RestRuleModel testRolePermissionsWith(UserRole userRole)
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a user and use them to create a private site containing a folder");
 | 
			
		||||
@@ -261,8 +355,41 @@ public class CreateRulesTests extends RestTest
 | 
			
		||||
        STEP(String.format("Add a user with '%s' role in the private site's folder", userRole.toString()));
 | 
			
		||||
        UserModel userWithRole = dataUser.createRandomTestUser();
 | 
			
		||||
        dataUser.addUserToSite(userWithRole, privateSite, userRole);
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel("testRule", List.of(createActionModel()));
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel("testRule", List.of(createDefaultActionModel()));
 | 
			
		||||
 | 
			
		||||
        return restClient.authenticateUser(userWithRole).withCoreAPI().usingNode(privateFolder).usingDefaultRuleSet().createSingleRule(ruleModel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can create a rule with several actions.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void createRuleWithActions()
 | 
			
		||||
    {
 | 
			
		||||
        final Map<String, Serializable> copyParams =
 | 
			
		||||
                Map.of("destination-folder", "dummy-folder-node", "deep-copy", true);
 | 
			
		||||
        final RestActionBodyExecTemplateModel copyAction = createCustomActionModel("copy", copyParams);
 | 
			
		||||
        final Map<String, Serializable> checkOutParams =
 | 
			
		||||
                Map.of("destination-folder", "dummy-folder-node", "assoc-name", "cm:checkout", "assoc-type",
 | 
			
		||||
                        "cm:contains");
 | 
			
		||||
        final RestActionBodyExecTemplateModel checkOutAction = createCustomActionModel("check-out", checkOutParams);
 | 
			
		||||
        final Map<String, Serializable> scriptParams = Map.of("script-ref", "dummy-script-node-id");
 | 
			
		||||
        final RestActionBodyExecTemplateModel scriptAction = createCustomActionModel("script", scriptParams);
 | 
			
		||||
        final RestRuleModel ruleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        ruleModel.setActions(Arrays.asList(copyAction, checkOutAction, scriptAction));
 | 
			
		||||
 | 
			
		||||
        final UserModel admin = dataUser.getAdminUser();
 | 
			
		||||
 | 
			
		||||
        final RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
                .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        final RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        expectedRuleModel.setActions(addActionContextParams(Arrays.asList(copyAction, checkOutAction, scriptAction)));
 | 
			
		||||
        expectedRuleModel.setConditions(createEmptyConditionModel());
 | 
			
		||||
        expectedRuleModel.setTriggers(List.of("inbound"));
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
 | 
			
		||||
                .assertThat().field("isShared").isNull();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,6 @@ import static org.springframework.http.HttpStatus.OK;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.RestTest;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleModel;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleModelsCollection;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleSetModel;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleSetModelsCollection;
 | 
			
		||||
import org.alfresco.utility.model.FolderModel;
 | 
			
		||||
@@ -122,7 +121,7 @@ public class GetRuleSetsTests extends RestTest
 | 
			
		||||
        STEP("Get the rule sets and owning folders");
 | 
			
		||||
        RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                                                 .usingNode(ruleFolder)
 | 
			
		||||
                                                 .usingParams("include=owningFolder")
 | 
			
		||||
                                                 .include("owningFolder")
 | 
			
		||||
                                                 .getListOfRuleSets();
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
@@ -132,6 +131,23 @@ public class GetRuleSetsTests extends RestTest
 | 
			
		||||
        ruleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can get the reason that a rule set is included in the list. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void getRuleSetsAndInclusionType()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Get the rule sets and inclusion type");
 | 
			
		||||
        RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                                                         .usingNode(ruleFolder)
 | 
			
		||||
                                                         .include("inclusionType")
 | 
			
		||||
                                                         .getListOfRuleSets();
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
        ruleSets.getEntries().get(0).onModel()
 | 
			
		||||
                .assertThat().field("inclusionType").is("owned")
 | 
			
		||||
                .assertThat().field("id").is(ruleSetId);
 | 
			
		||||
        ruleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can get a rule set by its id. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void getRuleSetById()
 | 
			
		||||
@@ -184,7 +200,7 @@ public class GetRuleSetsTests extends RestTest
 | 
			
		||||
        STEP("Get the rule set and owning folder");
 | 
			
		||||
        RestRuleSetModel ruleSet = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                                             .usingNode(ruleFolder)
 | 
			
		||||
                                             .usingParams("include=owningFolder")
 | 
			
		||||
                                             .include("owningFolder")
 | 
			
		||||
                                             .getRuleSet(ruleSetId);
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
 
 | 
			
		||||
@@ -27,13 +27,14 @@ package org.alfresco.rest.rules;
 | 
			
		||||
 | 
			
		||||
import static java.util.stream.Collectors.toList;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.*;
 | 
			
		||||
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
 | 
			
		||||
import static org.alfresco.utility.report.log.Step.STEP;
 | 
			
		||||
import static org.junit.Assert.assertTrue;
 | 
			
		||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
 | 
			
		||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
 | 
			
		||||
import static org.springframework.http.HttpStatus.OK;
 | 
			
		||||
import static org.springframework.http.HttpStatus.CREATED;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.IntStream;
 | 
			
		||||
@@ -60,6 +61,8 @@ public class GetRulesTests extends RestTest
 | 
			
		||||
    private FolderModel ruleFolder;
 | 
			
		||||
    private List<RestRuleModel> createdRules;
 | 
			
		||||
    private RestRuleModel createdRuleA;
 | 
			
		||||
    private static final String IGNORE_ID = "id";
 | 
			
		||||
    private static final String IGNORE_IS_SHARED = "isShared";
 | 
			
		||||
 | 
			
		||||
    @BeforeClass(alwaysRun = true)
 | 
			
		||||
    public void dataPreparation()
 | 
			
		||||
@@ -91,7 +94,11 @@ public class GetRulesTests extends RestTest
 | 
			
		||||
        assertTrue("Expected no rules to be present.", rules.isEmpty());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can get all the rules for a folder. */
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can get all the rules for a folder.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Also check that the isShared field is not returned when not requested.
 | 
			
		||||
     */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void getRulesList()
 | 
			
		||||
    {
 | 
			
		||||
@@ -102,8 +109,9 @@ public class GetRulesTests extends RestTest
 | 
			
		||||
        rules.assertThat().entriesListCountIs(createdRules.size());
 | 
			
		||||
        IntStream.range(0, createdRules.size()).forEach(i ->
 | 
			
		||||
                rules.getEntries().get(i).onModel()
 | 
			
		||||
                         .assertThat().field("id").is(createdRules.get(i).getId())
 | 
			
		||||
                         .assertThat().field("name").is(createdRules.get(i).getName()));
 | 
			
		||||
                     .assertThat().field("id").is(createdRules.get(i).getId())
 | 
			
		||||
                     .assertThat().field("name").is(createdRules.get(i).getName())
 | 
			
		||||
                     .assertThat().field("isShared").isNull());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we get a 404 if trying to load rules for a folder that doesn't exist. */
 | 
			
		||||
@@ -128,7 +136,33 @@ public class GetRulesTests extends RestTest
 | 
			
		||||
        restClient.assertStatusCodeIs(NOT_FOUND);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can get a rule by its id. */
 | 
			
		||||
    /** Check we can get all the rules for a folder along with the extra "include" and "other" fields. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void getRulesListWithIncludedFields()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Get the rules that apply to the folder");
 | 
			
		||||
        RestRuleModelsCollection rules = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
                                                   .include("isShared")
 | 
			
		||||
                                                   .getListOfRules();
 | 
			
		||||
 | 
			
		||||
        rules.assertThat().entriesListCountIs(createdRules.size());
 | 
			
		||||
        IntStream.range(0, createdRules.size()).forEach(i ->
 | 
			
		||||
                rules.getEntries().get(i).onModel()
 | 
			
		||||
                     .assertThat().field("isShared").isNotNull()
 | 
			
		||||
                        .assertThat().field("description").isNull()
 | 
			
		||||
                        .assertThat().field("enabled").is(false)
 | 
			
		||||
                        .assertThat().field("cascade").is(false)
 | 
			
		||||
                        .assertThat().field("asynchronous").is(false)
 | 
			
		||||
                        .assertThat().field("errorScript").isNull()
 | 
			
		||||
                        .assertThat().field("shared").isNull()
 | 
			
		||||
                        .assertThat().field("triggers").is("[inbound]"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can get a rule by its id.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Also check that the isShared field is not returned when not requested.
 | 
			
		||||
     */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void getSingleRule()
 | 
			
		||||
    {
 | 
			
		||||
@@ -138,7 +172,56 @@ public class GetRulesTests extends RestTest
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
 | 
			
		||||
        rule.assertThat().field("id").is(createdRuleA.getId())
 | 
			
		||||
            .assertThat().field("name").is(createdRuleA.getName());
 | 
			
		||||
            .assertThat().field("name").is(createdRuleA.getName())
 | 
			
		||||
            .assertThat().field("isShared").isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can get rule's other fields */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void getRulesOtherFieldsModified()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a rule with all other fields default values modified");
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModelWithModifiedValues();
 | 
			
		||||
        ruleModel.setTriggers(List.of("update"));
 | 
			
		||||
        UserModel admin = dataUser.getAdminUser();
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(folder).usingDefaultRuleSet()
 | 
			
		||||
                .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        RestRuleModel expectedRuleModel = createRuleModelWithModifiedValues();
 | 
			
		||||
        expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
 | 
			
		||||
        expectedRuleModel.setTriggers(List.of("update"));
 | 
			
		||||
        expectedRuleModel.setConditions(createEmptyConditionModel());
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
 | 
			
		||||
                .assertThat().field("id").isNotNull()
 | 
			
		||||
                .assertThat().field("isShared").isNull();
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can get rule's "other" fields */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void getRulesDefaultFields()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a rule with all other fields default values");
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        UserModel admin = dataUser.getAdminUser();
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(admin).withCoreAPI().usingNode(folder).usingDefaultRuleSet()
 | 
			
		||||
                .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        RestRuleModel expectedRuleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        expectedRuleModel.setActions(addActionContextParams(expectedRuleModel.getActions()));
 | 
			
		||||
        expectedRuleModel.setTriggers(List.of("inbound"));
 | 
			
		||||
        expectedRuleModel.setConditions(createEmptyConditionModel());
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        rule.assertThat().isEqualTo(expectedRuleModel, IGNORE_ID, IGNORE_IS_SHARED)
 | 
			
		||||
                .assertThat().field("id").isNotNull()
 | 
			
		||||
                .assertThat().field("isShared").isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we get a 404 if trying to load a rule from a folder that doesn't exist. */
 | 
			
		||||
@@ -174,6 +257,18 @@ public class GetRulesTests extends RestTest
 | 
			
		||||
        restClient.assertStatusCodeIs(NOT_FOUND);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can get a rule by its id along with any included fields. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void getSingleRuleWithIncludedFields()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Load a particular rule");
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
                                       .include("isShared")
 | 
			
		||||
                                       .getSingleRule(createdRuleA.getId());
 | 
			
		||||
 | 
			
		||||
        rule.assertThat().field("isShared").isNotNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check that a user without read permission cannot view the folder rules. */
 | 
			
		||||
    public void requireReadPermissionToGetRule()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,313 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
 | 
			
		||||
import static org.alfresco.utility.report.log.Step.STEP;
 | 
			
		||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
 | 
			
		||||
import static org.springframework.http.HttpStatus.CREATED;
 | 
			
		||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.dataprep.CMISUtil;
 | 
			
		||||
import org.alfresco.rest.RestTest;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleModel;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleModelsCollection;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleSetLinkModel;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleSetModel;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleSetModelsCollection;
 | 
			
		||||
import org.alfresco.utility.model.FileModel;
 | 
			
		||||
import org.alfresco.utility.model.FolderModel;
 | 
			
		||||
import org.alfresco.utility.model.SiteModel;
 | 
			
		||||
import org.alfresco.utility.model.TestGroup;
 | 
			
		||||
import org.alfresco.utility.model.UserModel;
 | 
			
		||||
import org.testng.annotations.BeforeClass;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests for /nodes/{nodeId}/rule-set-links.
 | 
			
		||||
 */
 | 
			
		||||
@Test(groups = {TestGroup.RULES})
 | 
			
		||||
public class RuleSetLinksTests extends RestTest
 | 
			
		||||
{
 | 
			
		||||
    private UserModel user;
 | 
			
		||||
    private SiteModel site;
 | 
			
		||||
 | 
			
		||||
    @BeforeClass(alwaysRun = true)
 | 
			
		||||
    public void dataPreparation()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a user and site.");
 | 
			
		||||
        user = dataUser.createRandomTestUser();
 | 
			
		||||
        site = dataSite.usingUser(user).createPublicRandomSite();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can link to folder containing a rule set.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void linkToFolderContainingRules()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create folders in existing site");
 | 
			
		||||
        final FolderModel ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create a rule in the rule folder.");
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel("ruleName");
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
                .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        STEP("Get the rule sets for the folder and find the rule set id");
 | 
			
		||||
        final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
 | 
			
		||||
                .getListOfRuleSets();
 | 
			
		||||
        ruleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
        final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
 | 
			
		||||
 | 
			
		||||
        STEP("Link to a rule folder");
 | 
			
		||||
        final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
 | 
			
		||||
        request.setId(ruleFolder.getNodeRef());
 | 
			
		||||
        final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert link result");
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        final RestRuleSetLinkModel expectedLink = new RestRuleSetLinkModel();
 | 
			
		||||
        expectedLink.setId(ruleSetId);
 | 
			
		||||
        ruleLink.assertThat().isEqualTo(expectedLink);
 | 
			
		||||
 | 
			
		||||
        STEP("Check if folder returns same rules");
 | 
			
		||||
        final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                .usingNode(folder)
 | 
			
		||||
                .usingDefaultRuleSet()
 | 
			
		||||
                .getListOfRules();
 | 
			
		||||
        linkedRules.assertThat().entriesListCountIs(1);
 | 
			
		||||
        linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
 | 
			
		||||
 | 
			
		||||
        STEP("Check if folder returns rule set with linked inclusionType");
 | 
			
		||||
        final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                .usingNode(folder)
 | 
			
		||||
                .include("inclusionType")
 | 
			
		||||
                .getListOfRuleSets();
 | 
			
		||||
        linkedRuleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
        final RestRuleSetModel expectedRuleSet = new RestRuleSetModel();
 | 
			
		||||
        expectedRuleSet.setId(ruleSetId);
 | 
			
		||||
        expectedRuleSet.setInclusionType("linked");
 | 
			
		||||
        linkedRuleSets.getEntries()
 | 
			
		||||
                .get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can link to a rule set.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void linkToRuleSet()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create folders in existing site");
 | 
			
		||||
        final FolderModel ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create a rule in the rule folder.");
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel("ruleName");
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
                .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        STEP("Get the rule sets for the folder and find the rule set id");
 | 
			
		||||
        final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder)
 | 
			
		||||
                .getListOfRuleSets();
 | 
			
		||||
        ruleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
        final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
 | 
			
		||||
 | 
			
		||||
        STEP("Link to a rule set");
 | 
			
		||||
        final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
 | 
			
		||||
        request.setId(ruleSetId);
 | 
			
		||||
        final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert link result");
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        final RestRuleSetLinkModel expectedLink = new RestRuleSetLinkModel();
 | 
			
		||||
        expectedLink.setId(ruleSetId);
 | 
			
		||||
        ruleLink.assertThat().isEqualTo(expectedLink);
 | 
			
		||||
 | 
			
		||||
        STEP("Check if folder returns same rules");
 | 
			
		||||
        final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                .usingNode(folder)
 | 
			
		||||
                .usingDefaultRuleSet()
 | 
			
		||||
                .getListOfRules();
 | 
			
		||||
        linkedRules.assertThat().entriesListCountIs(1);
 | 
			
		||||
        linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
 | 
			
		||||
 | 
			
		||||
        STEP("Check if folder returns rule set with linked inclusionType");
 | 
			
		||||
        final RestRuleSetModelsCollection likedRuleSets = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                .usingNode(folder)
 | 
			
		||||
                .include("inclusionType")
 | 
			
		||||
                .getListOfRuleSets();
 | 
			
		||||
        likedRuleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
        final RestRuleSetModel expectedRuleSet = new RestRuleSetModel();
 | 
			
		||||
        expectedRuleSet.setId(ruleSetId);
 | 
			
		||||
        expectedRuleSet.setInclusionType("linked");
 | 
			
		||||
        likedRuleSets.getEntries()
 | 
			
		||||
                .get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we get 404 when linking to a non-existing rule set/folder.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void linkToNonExistingRuleSet()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder in existing site");
 | 
			
		||||
        final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Link to non-existing rule set");
 | 
			
		||||
        final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
 | 
			
		||||
        request.setId("dummy-rule-set-id");
 | 
			
		||||
        restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert link result is 404");
 | 
			
		||||
        restClient.assertStatusCodeIs(NOT_FOUND);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we get bad request error when linking to a folder without rules.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void linkToFolderWithoutRules()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create 2 folders without rules in existing site");
 | 
			
		||||
        final FolderModel folder1 = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        final FolderModel folder2 = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Link to a folder without rules");
 | 
			
		||||
        final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
 | 
			
		||||
        request.setId(folder2.getNodeRef());
 | 
			
		||||
        restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).createRuleLink(request);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert link result is 400");
 | 
			
		||||
        restClient.assertStatusCodeIs(BAD_REQUEST)
 | 
			
		||||
                .assertLastError().containsSummary("The target node has no rules to link.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we get bad request error when linking from a folder which already has rules.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void linkFromFolderWithRules()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create folders in existing site");
 | 
			
		||||
        final FolderModel folder1 = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        final FolderModel folder2 = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create rules in both folders.");
 | 
			
		||||
        RestRuleModel ruleModel1 = createRuleModel("ruleName1");
 | 
			
		||||
        restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).usingDefaultRuleSet()
 | 
			
		||||
                .createSingleRule(ruleModel1);
 | 
			
		||||
        RestRuleModel ruleModel2 = createRuleModel("ruleName2");
 | 
			
		||||
        restClient.authenticateUser(user).withCoreAPI().usingNode(folder2).usingDefaultRuleSet()
 | 
			
		||||
                .createSingleRule(ruleModel2);
 | 
			
		||||
 | 
			
		||||
        STEP("Link from a folder with rules");
 | 
			
		||||
        final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
 | 
			
		||||
        request.setId(folder2.getNodeRef());
 | 
			
		||||
        restClient.authenticateUser(user).withCoreAPI().usingNode(folder1).createRuleLink(request);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert link result is 400");
 | 
			
		||||
        restClient.assertStatusCodeIs(BAD_REQUEST)
 | 
			
		||||
                .assertLastError().containsSummary(
 | 
			
		||||
                "Unable to link to a ruleset because the folder has pre-existing rules or is already linked to a ruleset.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we get bad request error when linking to a file node.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void linkToFileNode()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder in existing site");
 | 
			
		||||
        final FolderModel folder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        final FileModel fileContent = dataContent.usingUser(user).usingSite(site).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
 | 
			
		||||
 | 
			
		||||
        STEP("Link to a file node");
 | 
			
		||||
        final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
 | 
			
		||||
        request.setId(fileContent.getNodeRef());
 | 
			
		||||
        restClient.authenticateUser(user).withCoreAPI().usingNode(folder).createRuleLink(request);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert link result is 400");
 | 
			
		||||
        restClient.assertStatusCodeIs(BAD_REQUEST)
 | 
			
		||||
                .assertLastError().containsSummary("NodeId of a folder is expected!");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can link to a parent folder with rules.
 | 
			
		||||
     */
 | 
			
		||||
    @Test(groups = {TestGroup.REST_API, TestGroup.RULES})
 | 
			
		||||
    public void linkToParentNodeWithRules()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create parent/child folders in existing site");
 | 
			
		||||
        final FolderModel parentFolder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
        final FolderModel childFolder = dataContent.usingUser(user).usingSite(site).usingResource(parentFolder).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Create a rule in the parent folder.");
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModel("ruleName");
 | 
			
		||||
        RestRuleModel rule = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolder).usingDefaultRuleSet()
 | 
			
		||||
                .createSingleRule(ruleModel);
 | 
			
		||||
 | 
			
		||||
        STEP("Get the rule sets for the folder and find the rule set id");
 | 
			
		||||
        final RestRuleSetModelsCollection ruleSets = restClient.authenticateUser(user).withCoreAPI().usingNode(parentFolder)
 | 
			
		||||
                .getListOfRuleSets();
 | 
			
		||||
        ruleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
        final String ruleSetId = ruleSets.getEntries().get(0).onModel().getId();
 | 
			
		||||
 | 
			
		||||
        STEP("Link to the parent folder");
 | 
			
		||||
        final RestRuleSetLinkModel request = new RestRuleSetLinkModel();
 | 
			
		||||
        request.setId(parentFolder.getNodeRef());
 | 
			
		||||
        final RestRuleSetLinkModel ruleLink = restClient.authenticateUser(user).withCoreAPI().usingNode(childFolder).createRuleLink(request);
 | 
			
		||||
 | 
			
		||||
        STEP("Assert link result");
 | 
			
		||||
        restClient.assertStatusCodeIs(CREATED);
 | 
			
		||||
        final RestRuleSetLinkModel expectedLink = new RestRuleSetLinkModel();
 | 
			
		||||
        expectedLink.setId(ruleSetId);
 | 
			
		||||
        ruleLink.assertThat().isEqualTo(expectedLink);
 | 
			
		||||
 | 
			
		||||
        STEP("Check if child folder returns same rules");
 | 
			
		||||
        final RestRuleModelsCollection linkedRules = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                .usingNode(childFolder)
 | 
			
		||||
                .usingDefaultRuleSet()
 | 
			
		||||
                .getListOfRules();
 | 
			
		||||
        linkedRules.assertThat().entriesListCountIs(1);
 | 
			
		||||
        linkedRules.getEntries().get(0).onModel().assertThat().isEqualTo(rule);
 | 
			
		||||
 | 
			
		||||
        STEP("Check if child folder returns rule set with linked inclusionType");
 | 
			
		||||
        final RestRuleSetModelsCollection linkedRuleSets = restClient.authenticateUser(user).withCoreAPI()
 | 
			
		||||
                .usingNode(childFolder)
 | 
			
		||||
                .include("inclusionType")
 | 
			
		||||
                .getListOfRuleSets();
 | 
			
		||||
        linkedRuleSets.assertThat().entriesListCountIs(1);
 | 
			
		||||
        final RestRuleSetModel expectedRuleSet = new RestRuleSetModel();
 | 
			
		||||
        expectedRuleSet.setId(ruleSetId);
 | 
			
		||||
        expectedRuleSet.setInclusionType("linked");
 | 
			
		||||
        linkedRuleSets.getEntries()
 | 
			
		||||
                .get(0).onModel().assertThat().isEqualTo(expectedRuleSet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -25,17 +25,53 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.rules;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.model.RestActionBodyExecTemplateModel;
 | 
			
		||||
import org.alfresco.rest.model.RestCompositeConditionDefinitionModel;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleModel;
 | 
			
		||||
 | 
			
		||||
public class RulesTestsUtils
 | 
			
		||||
{
 | 
			
		||||
    static final String RULE_NAME_DEFAULT = "ruleName";
 | 
			
		||||
    static final String RULE_DESCRIPTION_DEFAULT = "rule description";
 | 
			
		||||
    static final boolean RULE_ENABLED_DEFAULT = true;
 | 
			
		||||
    static final boolean RULE_CASCADE_DEFAULT = true;
 | 
			
		||||
    static final boolean RULE_ASYNC_DEFAULT = true;
 | 
			
		||||
    static final boolean RULE_SHARED_DEFAULT = false;
 | 
			
		||||
    static final String RULE_ERROR_SCRIPT_DEFAULT = "error-script";
 | 
			
		||||
    static final List<String> ruleTriggersDefault = List.of("inbound", "update", "outbound");
 | 
			
		||||
 | 
			
		||||
    public static RestRuleModel createRuleModel(String name) {
 | 
			
		||||
        return createRuleModel(name, List.of(createActionModel()));
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a rule model filled with default values.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The created rule model.
 | 
			
		||||
     */
 | 
			
		||||
    public static RestRuleModel createRuleModelWithModifiedValues()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel ruleModel = createRuleModelWithDefaultValues();
 | 
			
		||||
        ruleModel.setDescription(RULE_DESCRIPTION_DEFAULT);
 | 
			
		||||
        ruleModel.setEnabled(RULE_ENABLED_DEFAULT);
 | 
			
		||||
        ruleModel.setCascade(RULE_CASCADE_DEFAULT);
 | 
			
		||||
        ruleModel.setAsynchronous(RULE_ASYNC_DEFAULT);
 | 
			
		||||
        ruleModel.setIsShared(RULE_SHARED_DEFAULT);
 | 
			
		||||
        ruleModel.setTriggers(ruleTriggersDefault);
 | 
			
		||||
        ruleModel.setErrorScript(RULE_ERROR_SCRIPT_DEFAULT);
 | 
			
		||||
 | 
			
		||||
        return ruleModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RestRuleModel createRuleModelWithDefaultValues()
 | 
			
		||||
    {
 | 
			
		||||
        return createRuleModel(RULE_NAME_DEFAULT, List.of(createDefaultActionModel()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RestRuleModel createRuleModel(String name)
 | 
			
		||||
    {
 | 
			
		||||
        return createRuleModel(name, List.of(createDefaultActionModel()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -58,11 +94,37 @@ public class RulesTestsUtils
 | 
			
		||||
     *
 | 
			
		||||
     * @return The created action model.
 | 
			
		||||
     */
 | 
			
		||||
    public static RestActionBodyExecTemplateModel createActionModel()
 | 
			
		||||
    public static RestActionBodyExecTemplateModel createDefaultActionModel()
 | 
			
		||||
    {
 | 
			
		||||
        RestActionBodyExecTemplateModel restActionModel = new RestActionBodyExecTemplateModel();
 | 
			
		||||
        restActionModel.setActionDefinitionId("add-features");
 | 
			
		||||
        restActionModel.setParams(Map.of("aspect-name", "{http://www.alfresco.org/model/audio/1.0}audio", "actionContext", "rule"));
 | 
			
		||||
        restActionModel.setActionDefinitionId("set-property-value");
 | 
			
		||||
        restActionModel.setParams(Map.of("aspect-name", "cm:audio"));
 | 
			
		||||
        return restActionModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<RestActionBodyExecTemplateModel> addActionContextParams(List<RestActionBodyExecTemplateModel> inputActions)
 | 
			
		||||
    {
 | 
			
		||||
        inputActions.forEach(inputAction -> {
 | 
			
		||||
            final Map<String, Serializable> params = new HashMap<>((Map<String, Serializable>) inputAction.getParams());
 | 
			
		||||
            params.put("actionContext", "rule");
 | 
			
		||||
            inputAction.setParams(params);
 | 
			
		||||
        });
 | 
			
		||||
        return inputActions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RestActionBodyExecTemplateModel createCustomActionModel(String actionDefinitionId, Map<String, Serializable> params)
 | 
			
		||||
    {
 | 
			
		||||
        RestActionBodyExecTemplateModel restActionModel = new RestActionBodyExecTemplateModel();
 | 
			
		||||
        restActionModel.setActionDefinitionId(actionDefinitionId);
 | 
			
		||||
        restActionModel.setParams(params);
 | 
			
		||||
        return restActionModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RestCompositeConditionDefinitionModel createEmptyConditionModel()
 | 
			
		||||
    {
 | 
			
		||||
        RestCompositeConditionDefinitionModel conditions = new RestCompositeConditionDefinitionModel();
 | 
			
		||||
        conditions.setInverted(false);
 | 
			
		||||
        conditions.setBooleanMode("and");
 | 
			
		||||
        return conditions;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,232 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Repository
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.requests.RuleSettings.IS_INHERITANCE_ENABLED;
 | 
			
		||||
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
 | 
			
		||||
import static org.alfresco.utility.report.log.Step.STEP;
 | 
			
		||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
 | 
			
		||||
import static org.springframework.http.HttpStatus.FORBIDDEN;
 | 
			
		||||
import static org.springframework.http.HttpStatus.NOT_FOUND;
 | 
			
		||||
import static org.springframework.http.HttpStatus.OK;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.RestTest;
 | 
			
		||||
import org.alfresco.rest.model.RestRuleSettingsModel;
 | 
			
		||||
import org.alfresco.utility.model.FolderModel;
 | 
			
		||||
import org.alfresco.utility.model.SiteModel;
 | 
			
		||||
import org.alfresco.utility.model.TestGroup;
 | 
			
		||||
import org.alfresco.utility.model.UserModel;
 | 
			
		||||
import org.testng.annotations.BeforeClass;
 | 
			
		||||
import org.testng.annotations.Test;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests for GET and PUT /nodes/{nodeId}/rule-settings/{ruleSettingKey}.
 | 
			
		||||
 */
 | 
			
		||||
@Test (groups = { TestGroup.RULES })
 | 
			
		||||
public class SetInheritanceTests extends RestTest
 | 
			
		||||
{
 | 
			
		||||
    private UserModel siteOwner;
 | 
			
		||||
    private SiteModel site;
 | 
			
		||||
 | 
			
		||||
    @BeforeClass (alwaysRun = true)
 | 
			
		||||
    public void dataPreparation()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a user, site and folder.");
 | 
			
		||||
        siteOwner = dataUser.createRandomTestUser();
 | 
			
		||||
        site = dataSite.usingUser(siteOwner).createPrivateRandomSite();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can get the -isInheritanceEnabled- rule setting for the folder. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void getIsInherited()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder for the test.");
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Get the -isInheritanceEnabled- rule settings for the folder.");
 | 
			
		||||
        RestRuleSettingsModel ruleSettingsModel = restClient.authenticateUser(siteOwner)
 | 
			
		||||
                                                            .withCoreAPI()
 | 
			
		||||
                                                            .usingResource(folder)
 | 
			
		||||
                                                            .usingIsInheritanceEnabledRuleSetting()
 | 
			
		||||
                                                            .retrieveSetting();
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
        RestRuleSettingsModel expected = new RestRuleSettingsModel();
 | 
			
		||||
        expected.setKey(IS_INHERITANCE_ENABLED);
 | 
			
		||||
        expected.setValue(true);
 | 
			
		||||
        ruleSettingsModel.assertThat().isEqualTo(expected);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we get an error when trying to get settings from a non-existent folder. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void getIsInheritedFromNonExistentFolder()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Try to get the -isInheritanceEnabled- rule settings for a fake folder.");
 | 
			
		||||
        FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
 | 
			
		||||
        nonExistentFolder.setNodeRef("fake-id");
 | 
			
		||||
        restClient.authenticateUser(siteOwner)
 | 
			
		||||
                  .withCoreAPI()
 | 
			
		||||
                  .usingResource(nonExistentFolder)
 | 
			
		||||
                  .usingIsInheritanceEnabledRuleSetting()
 | 
			
		||||
                  .retrieveSetting();
 | 
			
		||||
 | 
			
		||||
        restClient.assertLastError().statusCodeIs(NOT_FOUND)
 | 
			
		||||
                  .containsSummary("The entity with id: fake-id was not found");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we get an error when trying to retrieve a non-existent setting. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void getNonExistentSetting()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder for the test.");
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Try to get a fake setting from the folder.");
 | 
			
		||||
        restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(folder).usingRuleSetting("-fakeRuleSetting-")
 | 
			
		||||
                  .retrieveSetting();
 | 
			
		||||
 | 
			
		||||
        restClient.assertLastError().statusCodeIs(NOT_FOUND)
 | 
			
		||||
                  .containsSummary("Unrecognised rule setting key -fakeRuleSetting-");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check a user without permission for the folder cannot get the -isInheritanceEnabled- rule setting. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void getIsInheritedWithoutPermission()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder and a user without permission to access it.");
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
 | 
			
		||||
        UserModel noPermissionUser = dataUser.createRandomTestUser();
 | 
			
		||||
 | 
			
		||||
        STEP("Try to get the -isInheritanceEnabled- setting without permission.");
 | 
			
		||||
        restClient.authenticateUser(noPermissionUser)
 | 
			
		||||
                  .withCoreAPI()
 | 
			
		||||
                  .usingResource(folder)
 | 
			
		||||
                  .usingIsInheritanceEnabledRuleSetting()
 | 
			
		||||
                  .retrieveSetting();
 | 
			
		||||
 | 
			
		||||
        restClient.assertLastError().statusCodeIs(FORBIDDEN)
 | 
			
		||||
                  .containsSummary("Cannot read from this node");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can change the -isInheritanceEnabled- rule setting for the folder. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void updateIsInherited()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder for the test.");
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Set -isInheritanceEnabled- to false.");
 | 
			
		||||
        RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
 | 
			
		||||
        updateBody.setValue(false);
 | 
			
		||||
 | 
			
		||||
        RestRuleSettingsModel ruleSettingsModel = restClient.authenticateUser(siteOwner)
 | 
			
		||||
                                              .withCoreAPI()
 | 
			
		||||
                                              .usingResource(folder)
 | 
			
		||||
                                              .usingIsInheritanceEnabledRuleSetting()
 | 
			
		||||
                                              .updateSetting(updateBody);
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
        RestRuleSettingsModel expected = new RestRuleSettingsModel();
 | 
			
		||||
        expected.setKey(IS_INHERITANCE_ENABLED);
 | 
			
		||||
        expected.setValue(false);
 | 
			
		||||
        ruleSettingsModel.assertThat().isEqualTo(expected);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we get an error when trying to set -isInheritanceEnabled- to something other than a boolean. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void updateInheritedWithBadValue()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder for the test.");
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Try to set -isInheritanceEnabled- to \"banana\".");
 | 
			
		||||
        RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
 | 
			
		||||
        updateBody.setValue("banana");
 | 
			
		||||
 | 
			
		||||
        restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(folder).usingIsInheritanceEnabledRuleSetting()
 | 
			
		||||
                  .updateSetting(updateBody);
 | 
			
		||||
 | 
			
		||||
        restClient.assertLastError().statusCodeIs(BAD_REQUEST)
 | 
			
		||||
                  .containsSummary("Rule setting " + IS_INHERITANCE_ENABLED + " requires a boolean value.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we get an error when the folder is not found. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void updateInheritedWithNonExistentFolder()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Try to set -isInheritanceEnabled- against a fake folder.");
 | 
			
		||||
        FolderModel nonExistentFolder = FolderModel.getRandomFolderModel();
 | 
			
		||||
        nonExistentFolder.setNodeRef("fake-id");
 | 
			
		||||
 | 
			
		||||
        RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
 | 
			
		||||
        updateBody.setValue(true);
 | 
			
		||||
 | 
			
		||||
        restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(nonExistentFolder).usingIsInheritanceEnabledRuleSetting()
 | 
			
		||||
                  .updateSetting(updateBody);
 | 
			
		||||
 | 
			
		||||
        restClient.assertLastError().statusCodeIs(NOT_FOUND)
 | 
			
		||||
                  .containsSummary("The entity with id: fake-id was not found");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we get an error when trying to set a non-existent setting. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void updateNonExistentSetting()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder for the test.");
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
 | 
			
		||||
 | 
			
		||||
        STEP("Try to set a fake setting on the folder.");
 | 
			
		||||
        RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
 | 
			
		||||
        updateBody.setValue(true);
 | 
			
		||||
 | 
			
		||||
        restClient.authenticateUser(siteOwner).withCoreAPI().usingResource(folder).usingRuleSetting("-fakeRuleSetting-")
 | 
			
		||||
                  .updateSetting(updateBody);
 | 
			
		||||
 | 
			
		||||
        restClient.assertLastError().statusCodeIs(NOT_FOUND)
 | 
			
		||||
                  .containsSummary("Unrecognised rule setting key -fakeRuleSetting-");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check a user without manage permission cannot update the -isInheritanceEnabled- rule setting. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES })
 | 
			
		||||
    public void updateIsInheritedWithoutPermission()
 | 
			
		||||
    {
 | 
			
		||||
        STEP("Create a folder and a collaborator.");
 | 
			
		||||
        FolderModel folder = dataContent.usingUser(siteOwner).usingSite(site).createFolder();
 | 
			
		||||
        UserModel collaborator = dataUser.createRandomTestUser();
 | 
			
		||||
        collaborator.setUserRole(SiteCollaborator);
 | 
			
		||||
        restClient.authenticateUser(siteOwner).withCoreAPI().usingSite(site).addPerson(collaborator);
 | 
			
		||||
 | 
			
		||||
        STEP("Try to update the -isInheritanceEnabled- setting without permission.");
 | 
			
		||||
        RestRuleSettingsModel updateBody = new RestRuleSettingsModel();
 | 
			
		||||
        updateBody.setValue(true);
 | 
			
		||||
 | 
			
		||||
        restClient.authenticateUser(collaborator).withCoreAPI().usingResource(folder).usingIsInheritanceEnabledRuleSetting()
 | 
			
		||||
                  .updateSetting(updateBody);
 | 
			
		||||
 | 
			
		||||
        restClient.assertLastError().statusCodeIs(FORBIDDEN)
 | 
			
		||||
                  .containsSummary("Insufficient permissions to manage rules");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.createActionModel;
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.createDefaultActionModel;
 | 
			
		||||
import static org.alfresco.rest.rules.RulesTestsUtils.createRuleModel;
 | 
			
		||||
import static org.alfresco.utility.constants.UserRole.SiteCollaborator;
 | 
			
		||||
import static org.alfresco.utility.report.log.Step.STEP;
 | 
			
		||||
@@ -64,7 +64,11 @@ public class UpdateRulesTests extends RestTest
 | 
			
		||||
        ruleFolder = dataContent.usingUser(user).usingSite(site).createFolder();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can update a rule. */
 | 
			
		||||
    /**
 | 
			
		||||
     * Check we can update a rule.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Also check that the isShared field is not returned when not requested.
 | 
			
		||||
     */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void updateRule()
 | 
			
		||||
    {
 | 
			
		||||
@@ -77,7 +81,8 @@ public class UpdateRulesTests extends RestTest
 | 
			
		||||
 | 
			
		||||
        restClient.assertStatusCodeIs(OK);
 | 
			
		||||
        updatedRule.assertThat().field("id").is(rule.getId())
 | 
			
		||||
                   .assertThat().field("name").is("Updated rule name");
 | 
			
		||||
                   .assertThat().field("name").is("Updated rule name")
 | 
			
		||||
                   .assertThat().field("isShared").isNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we get a 404 if trying to update a rule in a folder that doesn't exist. */
 | 
			
		||||
@@ -156,8 +161,7 @@ public class UpdateRulesTests extends RestTest
 | 
			
		||||
        RestRuleModel rule = createAndSaveRule("Rule name");
 | 
			
		||||
 | 
			
		||||
        STEP("Try to update the rule to have no name.");
 | 
			
		||||
        RestRuleModel updatedRuleModel = new RestRuleModel();
 | 
			
		||||
        updatedRuleModel.setName("");
 | 
			
		||||
        RestRuleModel updatedRuleModel = createRuleModel("");
 | 
			
		||||
        restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet().updateRule(rule.getId(), updatedRuleModel);
 | 
			
		||||
 | 
			
		||||
        restClient.assertLastError().statusCodeIs(BAD_REQUEST)
 | 
			
		||||
@@ -179,9 +183,24 @@ public class UpdateRulesTests extends RestTest
 | 
			
		||||
        updatedRule.assertThat().field("id").is(rule.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check we can update a rule and get the included fields. */
 | 
			
		||||
    @Test (groups = { TestGroup.REST_API, TestGroup.RULES, TestGroup.SANITY })
 | 
			
		||||
    public void updateRuleWithIncludedFields()
 | 
			
		||||
    {
 | 
			
		||||
        RestRuleModel rule = createAndSaveRule("Rule name");
 | 
			
		||||
 | 
			
		||||
        STEP("Try to update the rule.");
 | 
			
		||||
        RestRuleModel updatedRuleModel = createRuleModel("Updated rule name");
 | 
			
		||||
        RestRuleModel updatedRule = restClient.authenticateUser(user).withCoreAPI().usingNode(ruleFolder).usingDefaultRuleSet()
 | 
			
		||||
                                              .include("isShared")
 | 
			
		||||
                                              .updateRule(rule.getId(), updatedRuleModel);
 | 
			
		||||
 | 
			
		||||
        updatedRule.assertThat().field("isShared").isNotNull();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private RestRuleModel createAndSaveRule(String name)
 | 
			
		||||
    {
 | 
			
		||||
        return createAndSaveRule(name, List.of(createActionModel()));
 | 
			
		||||
        return createAndSaveRule(name, List.of(createDefaultActionModel()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-tests</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <developers>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo-packaging</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <properties>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								pom.xml
									
									
									
									
									
								
							@@ -2,7 +2,7 @@
 | 
			
		||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 | 
			
		||||
    <modelVersion>4.0.0</modelVersion>
 | 
			
		||||
    <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
    <version>17.79</version>
 | 
			
		||||
    <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    <packaging>pom</packaging>
 | 
			
		||||
    <name>Alfresco Community Repo Parent</name>
 | 
			
		||||
 | 
			
		||||
@@ -45,14 +45,14 @@
 | 
			
		||||
 | 
			
		||||
        <dependency.alfresco-hb-data-sender.version>1.0.12</dependency.alfresco-hb-data-sender.version>
 | 
			
		||||
        <dependency.alfresco-trashcan-cleaner.version>2.4.1</dependency.alfresco-trashcan-cleaner.version>
 | 
			
		||||
        <dependency.alfresco-jlan.version>7.1</dependency.alfresco-jlan.version>
 | 
			
		||||
        <dependency.alfresco-jlan.version>7.2</dependency.alfresco-jlan.version>
 | 
			
		||||
        <dependency.alfresco-server-root.version>6.0.1</dependency.alfresco-server-root.version>
 | 
			
		||||
        <dependency.alfresco-messaging-repo.version>1.2.20</dependency.alfresco-messaging-repo.version>
 | 
			
		||||
        <dependency.alfresco-log-sanitizer.version>0.2</dependency.alfresco-log-sanitizer.version>
 | 
			
		||||
        <dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
 | 
			
		||||
        <dependency.activiti.version>5.23.0</dependency.activiti.version>
 | 
			
		||||
        <dependency.alfresco-transform-service.version>1.5.3</dependency.alfresco-transform-service.version>
 | 
			
		||||
        <dependency.alfresco-transform-core.version>2.6.0</dependency.alfresco-transform-core.version>
 | 
			
		||||
        <dependency.alfresco-transform-service.version>1.5.4-A3</dependency.alfresco-transform-service.version>
 | 
			
		||||
        <dependency.alfresco-transform-core.version>2.7.0-A1</dependency.alfresco-transform-core.version>
 | 
			
		||||
        <dependency.alfresco-greenmail.version>6.4</dependency.alfresco-greenmail.version>
 | 
			
		||||
        <dependency.acs-event-model.version>0.0.16</dependency.acs-event-model.version>
 | 
			
		||||
 | 
			
		||||
@@ -74,7 +74,7 @@
 | 
			
		||||
        <dependency.httpcore.version>4.4.15</dependency.httpcore.version>
 | 
			
		||||
        <dependency.commons-httpclient.version>3.1-HTTPCLIENT-1265</dependency.commons-httpclient.version>
 | 
			
		||||
        <dependency.xercesImpl.version>2.12.2</dependency.xercesImpl.version>
 | 
			
		||||
        <dependency.slf4j.version>1.7.35</dependency.slf4j.version>
 | 
			
		||||
        <dependency.slf4j.version>1.7.36</dependency.slf4j.version>
 | 
			
		||||
        <dependency.gytheio.version>0.16</dependency.gytheio.version>
 | 
			
		||||
        <dependency.groovy.version>3.0.12</dependency.groovy.version>
 | 
			
		||||
        <dependency.tika.version>2.4.1</dependency.tika.version>
 | 
			
		||||
@@ -82,7 +82,7 @@
 | 
			
		||||
        <dependency.truezip.version>7.7.10</dependency.truezip.version>
 | 
			
		||||
        <dependency.poi.version>5.2.2</dependency.poi.version>
 | 
			
		||||
        <dependency.ooxml-schemas.version>1.4</dependency.ooxml-schemas.version>
 | 
			
		||||
        <dependency.keycloak.version>15.0.2</dependency.keycloak.version>
 | 
			
		||||
        <dependency.keycloak.version>18.0.0</dependency.keycloak.version>
 | 
			
		||||
        <dependency.jboss.logging.version>3.5.0.Final</dependency.jboss.logging.version>
 | 
			
		||||
        <dependency.camel.version>3.15.0</dependency.camel.version> <!-- when bumping this version, please keep track/sync with included netty.io dependencies (can cause dependency conflicts)-->
 | 
			
		||||
        <dependency.activemq.version>5.17.1</dependency.activemq.version>
 | 
			
		||||
@@ -120,11 +120,11 @@
 | 
			
		||||
        <dependency.mariadb.version>2.7.4</dependency.mariadb.version>
 | 
			
		||||
        <dependency.tas-utility.version>3.0.49</dependency.tas-utility.version>
 | 
			
		||||
        <dependency.rest-assured.version>5.1.1</dependency.rest-assured.version>
 | 
			
		||||
        <dependency.tas-restapi.version>1.103</dependency.tas-restapi.version>
 | 
			
		||||
        <dependency.tas-cmis.version>1.31</dependency.tas-cmis.version>
 | 
			
		||||
        <dependency.tas-email.version>1.8</dependency.tas-email.version>
 | 
			
		||||
        <dependency.tas-webdav.version>1.6</dependency.tas-webdav.version>
 | 
			
		||||
        <dependency.tas-ftp.version>1.5</dependency.tas-ftp.version>
 | 
			
		||||
        <dependency.tas-restapi.version>1.115</dependency.tas-restapi.version>
 | 
			
		||||
        <dependency.tas-cmis.version>1.32</dependency.tas-cmis.version>
 | 
			
		||||
        <dependency.tas-email.version>1.9</dependency.tas-email.version>
 | 
			
		||||
        <dependency.tas-webdav.version>1.7</dependency.tas-webdav.version>
 | 
			
		||||
        <dependency.tas-ftp.version>1.7</dependency.tas-ftp.version>
 | 
			
		||||
        <dependency.tas-dataprep.version>2.6</dependency.tas-dataprep.version>
 | 
			
		||||
 | 
			
		||||
        <!-- AGS properties shared between community and enterprise -->
 | 
			
		||||
@@ -148,7 +148,7 @@
 | 
			
		||||
        <connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
 | 
			
		||||
        <developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
 | 
			
		||||
        <url>https://github.com/Alfresco/alfresco-community-repo</url>
 | 
			
		||||
        <tag>17.79</tag>
 | 
			
		||||
        <tag>HEAD</tag>
 | 
			
		||||
    </scm>
 | 
			
		||||
 | 
			
		||||
    <distributionManagement>
 | 
			
		||||
@@ -616,6 +616,12 @@
 | 
			
		||||
                <groupId>org.slf4j</groupId>
 | 
			
		||||
                <artifactId>slf4j-reload4j</artifactId>
 | 
			
		||||
                <version>${dependency.slf4j.version}</version>
 | 
			
		||||
                <exclusions>
 | 
			
		||||
                    <exclusion>
 | 
			
		||||
                        <groupId>ch.qos.reload4j</groupId>
 | 
			
		||||
                        <artifactId>reload4j</artifactId>
 | 
			
		||||
                    </exclusion>
 | 
			
		||||
                </exclusions>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>xerces</groupId>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <dependencies>
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.io.UnsupportedEncodingException;
 | 
			
		||||
import java.net.SocketException;
 | 
			
		||||
import java.net.URLEncoder;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
@@ -59,6 +60,7 @@ import org.alfresco.service.namespace.QName;
 | 
			
		||||
import org.alfresco.util.TempFileProvider;
 | 
			
		||||
import org.apache.commons.logging.Log;
 | 
			
		||||
import org.apache.commons.logging.LogFactory;
 | 
			
		||||
import org.apache.cxf.attachment.Rfc5987Util;
 | 
			
		||||
import org.springframework.context.ResourceLoaderAware;
 | 
			
		||||
import org.springframework.core.io.ResourceLoader;
 | 
			
		||||
import org.springframework.extensions.webscripts.Cache;
 | 
			
		||||
@@ -472,7 +474,7 @@ public class ContentStreamer implements ResourceLoaderAware
 | 
			
		||||
 | 
			
		||||
                if (req == null)
 | 
			
		||||
                {
 | 
			
		||||
                    headerValue += "; filename*=UTF-8''" + URLEncoder.encode(attachFileName, StandardCharsets.UTF_8)
 | 
			
		||||
                    headerValue += "; filename*=UTF-8''" + encodeFilename(attachFileName)
 | 
			
		||||
                            + "; filename=\"" + filterNameForQuotedString(attachFileName) + "\"";
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
@@ -481,12 +483,12 @@ public class ContentStreamer implements ResourceLoaderAware
 | 
			
		||||
                    boolean isLegacy = (null != userAgent) && (userAgent.contains("MSIE 8") || userAgent.contains("MSIE 7"));
 | 
			
		||||
                    if (isLegacy)
 | 
			
		||||
                    {
 | 
			
		||||
                        headerValue += "; filename=\"" + URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
 | 
			
		||||
                        headerValue += "; filename=\"" + encodeFilename(attachFileName);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        headerValue += "; filename=\"" + filterNameForQuotedString(attachFileName) + "\"; filename*=UTF-8''"
 | 
			
		||||
                                + URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
 | 
			
		||||
                                + encodeFilename(attachFileName);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -496,6 +498,21 @@ public class ContentStreamer implements ResourceLoaderAware
 | 
			
		||||
            res.setHeader("Content-Disposition", headerValue);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String encodeFilename(String attachFileName)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            return Rfc5987Util.encode(attachFileName);
 | 
			
		||||
        }
 | 
			
		||||
        catch (UnsupportedEncodingException e)
 | 
			
		||||
        {
 | 
			
		||||
            if (logger.isInfoEnabled())
 | 
			
		||||
                logger.info(e.getMessage() + " Changing encoder from Rfc5987Util to java.net.URLEncoder.");
 | 
			
		||||
 | 
			
		||||
            return URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    protected String filterNameForQuotedString(String s)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -78,7 +78,7 @@ public abstract class AbstractRuleWebScript extends DeclarativeWebScript
 | 
			
		||||
    private static final String RULE_OUTBOUND = "outbound";
 | 
			
		||||
    private static final String ACTION_CHECK_OUT = "check-out";
 | 
			
		||||
 | 
			
		||||
    private static final String CANNOT_CREATE_RULE = "cannot.create.rule.checkout.outbound";
 | 
			
		||||
    public static final String CANNOT_CREATE_RULE = "cannot.create.rule.checkout.outbound";
 | 
			
		||||
    
 | 
			
		||||
    protected NodeService nodeService;
 | 
			
		||||
    protected RuleService ruleService;
 | 
			
		||||
 
 | 
			
		||||
@@ -27,8 +27,8 @@ package org.alfresco.rest.api;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Rule;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSet;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSetLink;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
@@ -58,4 +58,9 @@ public interface RuleSets
 | 
			
		||||
     * @return {@link RuleSet} definition
 | 
			
		||||
     */
 | 
			
		||||
    RuleSet getRuleSetById(String folderNodeId, String ruleSetId, List<String> includes);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Link a rule set to a folder
 | 
			
		||||
     */
 | 
			
		||||
    RuleSetLink linkToRuleSet(String folderNodeId, String linkToNodeId);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,54 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSetting;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Rule settings API.
 | 
			
		||||
 */
 | 
			
		||||
@Experimental
 | 
			
		||||
public interface RuleSettings
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the rule setting with the given key.
 | 
			
		||||
     *
 | 
			
		||||
     * @param folderId Folder node ID
 | 
			
		||||
     * @param ruleSettingKey Rule setting key
 | 
			
		||||
     * @return {@link RuleSetting} The retrieved rule setting object.
 | 
			
		||||
     */
 | 
			
		||||
    RuleSetting getRuleSetting(String folderId, String ruleSettingKey);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the rule setting against the specified folder.
 | 
			
		||||
     *
 | 
			
		||||
     * @param folderId The folder to update.
 | 
			
		||||
     * @param ruleSetting The new rule setting.
 | 
			
		||||
     * @return The updated rule setting object.
 | 
			
		||||
     */
 | 
			
		||||
    RuleSetting setRuleSetting(String folderId, RuleSetting ruleSetting);
 | 
			
		||||
}
 | 
			
		||||
@@ -26,6 +26,8 @@
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Rule;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
 | 
			
		||||
@@ -33,8 +35,6 @@ import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.rule.RuleServiceException;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Folder node rules API.
 | 
			
		||||
 *
 | 
			
		||||
@@ -47,10 +47,11 @@ public interface Rules
 | 
			
		||||
     *
 | 
			
		||||
     * @param folderNodeId - folder node ID
 | 
			
		||||
     * @param ruleSetId - rule set ID
 | 
			
		||||
     * @param includes - The list of optional fields to include in the response.
 | 
			
		||||
     * @param paging - {@link Paging} information
 | 
			
		||||
     * @return {@link CollectionWithPagingInfo} containing a list page of folder rules
 | 
			
		||||
     */
 | 
			
		||||
    CollectionWithPagingInfo<Rule> getRules(String folderNodeId, String ruleSetId, Paging paging);
 | 
			
		||||
    CollectionWithPagingInfo<Rule> getRules(String folderNodeId, String ruleSetId, List<String> includes, Paging paging);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get rule for rule's ID and check associations with folder node and rule set node
 | 
			
		||||
@@ -58,9 +59,10 @@ public interface Rules
 | 
			
		||||
     * @param folderNodeId - folder node ID
 | 
			
		||||
     * @param ruleSetId - rule set ID
 | 
			
		||||
     * @param ruleId - rule ID
 | 
			
		||||
     * @param includes - The list of optional fields to include in the response.
 | 
			
		||||
     * @return {@link Rule} definition
 | 
			
		||||
     */
 | 
			
		||||
    Rule getRuleById(String folderNodeId, String ruleSetId, String ruleId);
 | 
			
		||||
    Rule getRuleById(String folderNodeId, String ruleSetId, String ruleId, List<String> includes);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create new rules (and potentially a rule set if "_default_" is supplied).
 | 
			
		||||
@@ -68,11 +70,12 @@ public interface Rules
 | 
			
		||||
     * @param folderNodeId The node id of a folder.
 | 
			
		||||
     * @param ruleSetId The id of a rule set (or "_default_" to use/create the default rule set for the folder).
 | 
			
		||||
     * @param rule The definition of the rule.
 | 
			
		||||
     * @param includes The list of optional fields to include in the response.
 | 
			
		||||
     * @return The newly created rules.
 | 
			
		||||
     * @throws InvalidArgumentException If the nodes are not the expected types, or the rule set does not correspond to the folder.
 | 
			
		||||
     * @throws RuleServiceException If the folder is already linked to another rule set.
 | 
			
		||||
     */
 | 
			
		||||
    List<Rule> createRules(String folderNodeId, String ruleSetId, List<Rule> rule);
 | 
			
		||||
    List<Rule> createRules(String folderNodeId, String ruleSetId, List<Rule> rule, List<String> includes);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Update a rule.
 | 
			
		||||
@@ -81,9 +84,10 @@ public interface Rules
 | 
			
		||||
     * @param ruleSetId The id of a rule set within the folder (or "_default_" to use the default rule set for the folder).
 | 
			
		||||
     * @param ruleId The rule id.
 | 
			
		||||
     * @param rule The new version of the rule.
 | 
			
		||||
     * @param includes The list of optional fields to include in the response.
 | 
			
		||||
     * @return The newly updated rule.
 | 
			
		||||
     */
 | 
			
		||||
    Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule);
 | 
			
		||||
    Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule, List<String> includes);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Delete rule for rule's ID and check associations with folder node and rule set node
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2021 Alfresco Software Limited
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software. 
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of 
 | 
			
		||||
@@ -713,6 +713,7 @@ public class CustomModelsImpl implements CustomModels
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            NodeRef nodeRef = customModelService.createDownloadNode(modelName, withForm);
 | 
			
		||||
            nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, modelName + DownloadsImpl.DEFAULT_ARCHIVE_EXTENSION);
 | 
			
		||||
            return new CustomModelDownload(nodeRef);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,156 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.action.ActionService;
 | 
			
		||||
import org.alfresco.service.cmr.action.ParameterDefinition;
 | 
			
		||||
import org.alfresco.service.cmr.action.ParameterizedItemDefinition;
 | 
			
		||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
 | 
			
		||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
 | 
			
		||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.StoreRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
 | 
			
		||||
import org.alfresco.service.namespace.NamespaceService;
 | 
			
		||||
import org.alfresco.service.namespace.QName;
 | 
			
		||||
import org.json.JSONArray;
 | 
			
		||||
import org.json.JSONException;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
public class ActionParameterConverter
 | 
			
		||||
{
 | 
			
		||||
    private final DictionaryService dictionaryService;
 | 
			
		||||
    private final ActionService actionService;
 | 
			
		||||
    private final NamespaceService namespaceService;
 | 
			
		||||
 | 
			
		||||
    public ActionParameterConverter(DictionaryService dictionaryService, ActionService actionService,
 | 
			
		||||
                                    NamespaceService namespaceService)
 | 
			
		||||
    {
 | 
			
		||||
        this.dictionaryService = dictionaryService;
 | 
			
		||||
        this.actionService = actionService;
 | 
			
		||||
        this.namespaceService = namespaceService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Map<String, Serializable> getConvertedParams(Map<String, Serializable> params, String name)
 | 
			
		||||
    {
 | 
			
		||||
        final Map<String, Serializable> parameters = new HashMap<>(params.size());
 | 
			
		||||
        final ParameterizedItemDefinition definition = actionService.getActionDefinition(name);
 | 
			
		||||
        if (definition == null)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{name});
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (Map.Entry<String, Serializable> param : params.entrySet())
 | 
			
		||||
        {
 | 
			
		||||
            final ParameterDefinition paramDef = definition.getParameterDefintion(param.getKey());
 | 
			
		||||
            if (paramDef == null && !definition.getAdhocPropertiesAllowed())
 | 
			
		||||
            {
 | 
			
		||||
                throw new InvalidArgumentException(InvalidArgumentException.DEFAULT_MESSAGE_ID, new String[]{param.getKey(), name});
 | 
			
		||||
            }
 | 
			
		||||
            if (paramDef != null)
 | 
			
		||||
            {
 | 
			
		||||
                final QName typeQName = paramDef.getType();
 | 
			
		||||
                parameters.put(param.getKey(), convertValue(typeQName, param.getValue()));
 | 
			
		||||
            } else
 | 
			
		||||
            {
 | 
			
		||||
                parameters.put(param.getKey(), param.getValue().toString());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return parameters;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Serializable convertParamFromServiceModel(Serializable param)
 | 
			
		||||
    {
 | 
			
		||||
        if (param instanceof QName)
 | 
			
		||||
        {
 | 
			
		||||
            return ((QName) param).toPrefixString(namespaceService);
 | 
			
		||||
        }
 | 
			
		||||
        else if (param instanceof NodeRef) {
 | 
			
		||||
            return ((NodeRef) param).getId();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return param;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Serializable convertValue(QName typeQName, Object propertyValue) throws JSONException
 | 
			
		||||
    {
 | 
			
		||||
        Serializable value;
 | 
			
		||||
 | 
			
		||||
        final DataTypeDefinition typeDef = dictionaryService.getDataType(typeQName);
 | 
			
		||||
        if (typeDef == null)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotFoundException(NotFoundException.DEFAULT_MESSAGE_ID, new String[]{typeQName.toPrefixString()});
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (propertyValue instanceof JSONArray)
 | 
			
		||||
        {
 | 
			
		||||
            final String javaClassName = typeDef.getJavaClassName();
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                Class.forName(javaClassName);
 | 
			
		||||
            } catch (ClassNotFoundException e)
 | 
			
		||||
            {
 | 
			
		||||
                throw new DictionaryException("Java class " + javaClassName + " of property type " + typeDef.getName() + " is invalid", e);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            final int length = ((JSONArray) propertyValue).length();
 | 
			
		||||
            final List<Serializable> list = new ArrayList<>(length);
 | 
			
		||||
            for (int i = 0; i < length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                list.add(convertValue(typeQName, ((JSONArray) propertyValue).get(i)));
 | 
			
		||||
            }
 | 
			
		||||
            value = (Serializable) list;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (typeQName.equals(DataTypeDefinition.QNAME) && typeQName.toString().contains(":"))
 | 
			
		||||
            {
 | 
			
		||||
                value = QName.createQName(propertyValue.toString(), namespaceService);
 | 
			
		||||
            }
 | 
			
		||||
            else if (typeQName.isMatch(DataTypeDefinition.NODE_REF))
 | 
			
		||||
            {
 | 
			
		||||
                value = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, propertyValue.toString());
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                value = (Serializable) DefaultTypeConverter.INSTANCE.convert(dictionaryService.getDataType(typeQName), propertyValue);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,85 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.repo.web.scripts.rule.AbstractRuleWebScript.CANNOT_CREATE_RULE;
 | 
			
		||||
import static org.alfresco.service.cmr.rule.RuleType.OUTBOUND;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.repo.action.CompositeActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.RuntimeActionService;
 | 
			
		||||
import org.alfresco.repo.action.access.ActionAccessRestriction;
 | 
			
		||||
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.action.Action;
 | 
			
		||||
import org.alfresco.service.cmr.rule.Rule;
 | 
			
		||||
import org.apache.commons.collections.CollectionUtils;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
public class ActionPermissionValidator
 | 
			
		||||
{
 | 
			
		||||
    private final RuntimeActionService runtimeActionService;
 | 
			
		||||
 | 
			
		||||
    public ActionPermissionValidator(RuntimeActionService runtimeActionService)
 | 
			
		||||
    {
 | 
			
		||||
        this.runtimeActionService = runtimeActionService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Rule validateRulePermissions(Rule rule)
 | 
			
		||||
    {
 | 
			
		||||
        final List<Action> actions = ((CompositeActionImpl) rule.getAction()).getActions();
 | 
			
		||||
 | 
			
		||||
        checkRestrictedAccessActions(actions);
 | 
			
		||||
        checkRuleOutboundHasNoCheckOutAction(rule, actions);
 | 
			
		||||
        return rule;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkRestrictedAccessActions(List<Action> actions) {
 | 
			
		||||
        actions.forEach(action -> {
 | 
			
		||||
            ActionAccessRestriction.setActionContext(action, ActionAccessRestriction.RULE_ACTION_CONTEXT);
 | 
			
		||||
            runtimeActionService.verifyActionAccessRestrictions(action);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkRuleOutboundHasNoCheckOutAction(Rule rule, List<Action> actions) {
 | 
			
		||||
        //TODO: rule types should never be empty in final implementation
 | 
			
		||||
        if (CollectionUtils.isNotEmpty(rule.getRuleTypes()) && rule.getRuleTypes().contains(OUTBOUND))
 | 
			
		||||
        {
 | 
			
		||||
            for (Action action : actions)
 | 
			
		||||
            {
 | 
			
		||||
                if (action.getActionDefinitionName().equalsIgnoreCase(CheckOutActionExecuter.NAME))
 | 
			
		||||
                {
 | 
			
		||||
                    throw new InvalidArgumentException(CANNOT_CREATE_RULE);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -33,12 +33,15 @@ import java.util.Set;
 | 
			
		||||
import org.alfresco.model.ContentModel;
 | 
			
		||||
import org.alfresco.repo.rule.RuleModel;
 | 
			
		||||
import org.alfresco.rest.api.Nodes;
 | 
			
		||||
import org.alfresco.rest.api.model.Node;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSet;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
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.rule.RuleService;
 | 
			
		||||
import org.alfresco.service.cmr.security.PermissionService;
 | 
			
		||||
import org.alfresco.service.namespace.QName;
 | 
			
		||||
@@ -52,6 +55,7 @@ public class NodeValidator
 | 
			
		||||
    private Nodes nodes;
 | 
			
		||||
    private RuleService ruleService;
 | 
			
		||||
    private PermissionService permissionService;
 | 
			
		||||
    private NodeService nodeService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Validates if folder node exists and the user has permission to use it.
 | 
			
		||||
@@ -65,20 +69,7 @@ public class NodeValidator
 | 
			
		||||
    public NodeRef validateFolderNode(final String folderNodeId, boolean requireChangePermission)
 | 
			
		||||
    {
 | 
			
		||||
        final NodeRef nodeRef = nodes.validateOrLookupNode(folderNodeId, null);
 | 
			
		||||
        if (requireChangePermission)
 | 
			
		||||
        {
 | 
			
		||||
            if (permissionService.hasPermission(nodeRef, CHANGE_PERMISSIONS) != ALLOWED)
 | 
			
		||||
            {
 | 
			
		||||
                throw new PermissionDeniedException("Insufficient permissions to manage rules.");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (permissionService.hasReadPermission(nodeRef) != ALLOWED)
 | 
			
		||||
            {
 | 
			
		||||
                throw new PermissionDeniedException("Cannot read from this node!");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        validatePermission(requireChangePermission, nodeRef);
 | 
			
		||||
        verifyNodeType(nodeRef, ContentModel.TYPE_FOLDER, null);
 | 
			
		||||
 | 
			
		||||
        return nodeRef;
 | 
			
		||||
@@ -114,6 +105,15 @@ public class NodeValidator
 | 
			
		||||
        return ruleSetNodeRef;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public NodeRef validateRuleSetNode(String linkToNodeId, boolean requireChangePermission)
 | 
			
		||||
    {
 | 
			
		||||
        final Node ruleSetNode = nodes.getNode(linkToNodeId);
 | 
			
		||||
        final ChildAssociationRef primaryParent = nodeService.getPrimaryParent(ruleSetNode.getNodeRef());
 | 
			
		||||
        final NodeRef parentNode = primaryParent.getParentRef();
 | 
			
		||||
        validatePermission(requireChangePermission, parentNode);
 | 
			
		||||
        return parentNode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Validates if rule node exists and associated rule set node matches.
 | 
			
		||||
@@ -142,6 +142,24 @@ public class NodeValidator
 | 
			
		||||
        return nodeRef;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void validatePermission(boolean requireChangePermission, NodeRef nodeRef)
 | 
			
		||||
    {
 | 
			
		||||
        if (requireChangePermission)
 | 
			
		||||
        {
 | 
			
		||||
            if (permissionService.hasPermission(nodeRef, CHANGE_PERMISSIONS) != ALLOWED)
 | 
			
		||||
            {
 | 
			
		||||
                throw new PermissionDeniedException("Insufficient permissions to manage rules.");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (permissionService.hasReadPermission(nodeRef) != ALLOWED)
 | 
			
		||||
            {
 | 
			
		||||
                throw new PermissionDeniedException("Cannot read from this node!");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void verifyNodeType(final NodeRef nodeRef, final QName expectedType, final String expectedTypeName)
 | 
			
		||||
    {
 | 
			
		||||
        final Set<QName> expectedTypes = Set.of(expectedType);
 | 
			
		||||
@@ -152,6 +170,16 @@ public class NodeValidator
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isRuleSetNode(String nodeId) {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            validateNode(nodeId, ContentModel.TYPE_SYSTEM_FOLDER, RULE_SET_EXPECTED_TYPE_NAME);
 | 
			
		||||
            return true;
 | 
			
		||||
        } catch (InvalidArgumentException e) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isRuleSetNotNullAndShared(final NodeRef ruleSetNodeRef, final NodeRef folderNodeRef)
 | 
			
		||||
    {
 | 
			
		||||
        if (ruleSetNodeRef == null && folderNodeRef != null)
 | 
			
		||||
@@ -184,4 +212,9 @@ public class NodeValidator
 | 
			
		||||
    {
 | 
			
		||||
        this.nodes = nodes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setNodeService(NodeService nodeService)
 | 
			
		||||
    {
 | 
			
		||||
        this.nodeService = nodeService;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,64 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Rule;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.rule.RuleService;
 | 
			
		||||
 | 
			
		||||
/** Responsible for creating {@link Rule} objects. */
 | 
			
		||||
@Experimental
 | 
			
		||||
public class RuleLoader
 | 
			
		||||
{
 | 
			
		||||
    public static final String IS_SHARED = "isShared";
 | 
			
		||||
    private RuleService ruleService;
 | 
			
		||||
    private NodeValidator nodeValidator;
 | 
			
		||||
 | 
			
		||||
    public Rule loadRule(org.alfresco.service.cmr.rule.Rule ruleModel, List<String> includes)
 | 
			
		||||
    {
 | 
			
		||||
        Rule rule = Rule.from(ruleModel);
 | 
			
		||||
        if (includes != null && includes.contains(IS_SHARED))
 | 
			
		||||
        {
 | 
			
		||||
            NodeRef ruleSet = ruleService.getRuleSetNode(ruleModel.getNodeRef());
 | 
			
		||||
            boolean isShared = nodeValidator.isRuleSetNotNullAndShared(ruleSet);
 | 
			
		||||
            rule.setIsShared(isShared);
 | 
			
		||||
        }
 | 
			
		||||
        return rule;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setRuleService(RuleService ruleService)
 | 
			
		||||
    {
 | 
			
		||||
        this.ruleService = ruleService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setNodeValidator(NodeValidator nodeValidator)
 | 
			
		||||
    {
 | 
			
		||||
        this.nodeValidator = nodeValidator;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -25,10 +25,15 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.InclusionType.INHERITED;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.InclusionType.LINKED;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.InclusionType.OWNED;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSet;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeService;
 | 
			
		||||
 | 
			
		||||
@@ -36,6 +41,8 @@ import org.alfresco.service.cmr.repository.NodeService;
 | 
			
		||||
@Experimental
 | 
			
		||||
public class RuleSetLoader
 | 
			
		||||
{
 | 
			
		||||
    protected static final String OWNING_FOLDER = "owningFolder";
 | 
			
		||||
    protected static final String INCLUSION_TYPE = "inclusionType";
 | 
			
		||||
    private NodeService nodeService;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -45,15 +52,33 @@ public class RuleSetLoader
 | 
			
		||||
     * @param includes A list of fields to include.
 | 
			
		||||
     * @return The rule set object.
 | 
			
		||||
     */
 | 
			
		||||
    protected RuleSet loadRuleSet(NodeRef ruleSetNodeRef, List<String> includes)
 | 
			
		||||
    public RuleSet loadRuleSet(NodeRef ruleSetNodeRef, NodeRef folderNodeRef, List<String> includes)
 | 
			
		||||
    {
 | 
			
		||||
        String ruleSetId = ruleSetNodeRef.getId();
 | 
			
		||||
        RuleSet ruleSet = RuleSet.of(ruleSetId);
 | 
			
		||||
 | 
			
		||||
        if (includes != null && includes.contains("owningFolder"))
 | 
			
		||||
        if (includes != null)
 | 
			
		||||
        {
 | 
			
		||||
            NodeRef parentRef = nodeService.getPrimaryParent(ruleSetNodeRef).getParentRef();
 | 
			
		||||
            ruleSet.setOwningFolder(parentRef);
 | 
			
		||||
            if (includes.contains(OWNING_FOLDER))
 | 
			
		||||
            {
 | 
			
		||||
                ruleSet.setOwningFolder(parentRef);
 | 
			
		||||
            }
 | 
			
		||||
            if (includes.contains(INCLUSION_TYPE))
 | 
			
		||||
            {
 | 
			
		||||
                // In the case that a rule set applies to the given folder for multiple reasons then priority is given to owned, then linked, then inherited.
 | 
			
		||||
                if (parentRef.equals(folderNodeRef))
 | 
			
		||||
                {
 | 
			
		||||
                    ruleSet.setInclusionType(OWNED);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    boolean linked = nodeService.getParentAssocs(ruleSetNodeRef)
 | 
			
		||||
                                           .stream().map(ChildAssociationRef::getParentRef)
 | 
			
		||||
                                           .anyMatch(folderNodeRef::equals);
 | 
			
		||||
                    ruleSet.setInclusionType(linked ? LINKED : INHERITED);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return ruleSet;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -31,13 +31,18 @@ import static java.util.stream.Collectors.toList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.repo.rule.RuleModel;
 | 
			
		||||
import org.alfresco.repo.rule.RuntimeRuleService;
 | 
			
		||||
import org.alfresco.rest.api.RuleSets;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSet;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSetLink;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.ListPage;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeService;
 | 
			
		||||
import org.alfresco.service.cmr.rule.RuleService;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
@@ -46,6 +51,8 @@ public class RuleSetsImpl implements RuleSets
 | 
			
		||||
    private RuleSetLoader ruleSetLoader;
 | 
			
		||||
    private RuleService ruleService;
 | 
			
		||||
    private NodeValidator validator;
 | 
			
		||||
    private NodeService nodeService;
 | 
			
		||||
    private RuntimeRuleService runtimeRuleService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public CollectionWithPagingInfo<RuleSet> getRuleSets(String folderNodeId, List<String> includes, Paging paging)
 | 
			
		||||
@@ -54,7 +61,8 @@ public class RuleSetsImpl implements RuleSets
 | 
			
		||||
 | 
			
		||||
        NodeRef ruleSetNode = ruleService.getRuleSetNode(folderNode);
 | 
			
		||||
        List<RuleSet> ruleSets = Optional.ofNullable(ruleSetNode)
 | 
			
		||||
                                         .map(nodeRef -> ruleSetLoader.loadRuleSet(nodeRef, includes)).stream().collect(toList());
 | 
			
		||||
                                         .map(nodeRef -> ruleSetLoader.loadRuleSet(nodeRef, folderNode, includes))
 | 
			
		||||
                                                                      .stream().collect(toList());
 | 
			
		||||
 | 
			
		||||
        return ListPage.of(ruleSets, paging);
 | 
			
		||||
    }
 | 
			
		||||
@@ -65,7 +73,38 @@ public class RuleSetsImpl implements RuleSets
 | 
			
		||||
        NodeRef folderNode = validator.validateFolderNode(folderNodeId, false);
 | 
			
		||||
        NodeRef ruleSetNode = validator.validateRuleSetNode(ruleSetId, folderNode);
 | 
			
		||||
 | 
			
		||||
        return ruleSetLoader.loadRuleSet(ruleSetNode, includes);
 | 
			
		||||
        return ruleSetLoader.loadRuleSet(ruleSetNode, folderNode, includes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleSetLink linkToRuleSet(String folderNodeId, String linkToNodeId)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId,true);
 | 
			
		||||
        final boolean isRuleSetNode = validator.isRuleSetNode(linkToNodeId);
 | 
			
		||||
        final NodeRef linkToNodeRef = isRuleSetNode
 | 
			
		||||
                ? validator.validateRuleSetNode(linkToNodeId, true)
 | 
			
		||||
                : validator.validateFolderNode(linkToNodeId, true);
 | 
			
		||||
 | 
			
		||||
        //The target node should have pre-existing rules to link to
 | 
			
		||||
        if (!ruleService.hasRules(linkToNodeRef)) {
 | 
			
		||||
            throw new InvalidArgumentException("The target node has no rules to link.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //The folder shouldn't have any pre-existing rules
 | 
			
		||||
        if (ruleService.hasRules(folderNodeRef)) {
 | 
			
		||||
            throw new InvalidArgumentException("Unable to link to a ruleset because the folder has pre-existing rules or is already linked to a ruleset.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create the destination folder as a secondary child of the first
 | 
			
		||||
        NodeRef ruleSetNodeRef = runtimeRuleService.getSavedRuleFolderAssoc(linkToNodeRef).getChildRef();
 | 
			
		||||
        // The required aspect will automatically be added to the node
 | 
			
		||||
        nodeService.addChild(folderNodeRef, ruleSetNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
 | 
			
		||||
 | 
			
		||||
        RuleSetLink ruleSetLink = new RuleSetLink();
 | 
			
		||||
        ruleSetLink.setId(ruleSetNodeRef.getId());
 | 
			
		||||
 | 
			
		||||
        return ruleSetLink;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setRuleSetLoader(RuleSetLoader ruleSetLoader)
 | 
			
		||||
@@ -82,4 +121,14 @@ public class RuleSetsImpl implements RuleSets
 | 
			
		||||
    {
 | 
			
		||||
        this.ruleService = ruleService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setNodeService(NodeService nodeService)
 | 
			
		||||
    {
 | 
			
		||||
        this.nodeService = nodeService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setRuntimeRuleService(RuntimeRuleService runtimeRuleService)
 | 
			
		||||
    {
 | 
			
		||||
        this.runtimeRuleService = runtimeRuleService;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,107 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.repo.rule.RuleModel.ASPECT_IGNORE_INHERITED_RULES;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.RuleSetting.IS_INHERITANCE_ENABLED_KEY;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.RuleSettings;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSetting;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeService;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
public class RuleSettingsImpl implements RuleSettings
 | 
			
		||||
{
 | 
			
		||||
    private NodeValidator validator;
 | 
			
		||||
    private NodeService nodeService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleSetting getRuleSetting(String folderId, String ruleSettingKey)
 | 
			
		||||
    {
 | 
			
		||||
        NodeRef folderNode = validator.validateFolderNode(folderId, false);
 | 
			
		||||
        switch (ruleSettingKey)
 | 
			
		||||
        {
 | 
			
		||||
            case IS_INHERITANCE_ENABLED_KEY:
 | 
			
		||||
                return getIsInheritanceEnabled(folderNode);
 | 
			
		||||
            default:
 | 
			
		||||
                throw new NotFoundException("Unrecognised rule setting key " + ruleSettingKey);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private RuleSetting getIsInheritanceEnabled(NodeRef folderNode)
 | 
			
		||||
    {
 | 
			
		||||
        boolean inheritanceDisabled = nodeService.hasAspect(folderNode, ASPECT_IGNORE_INHERITED_RULES);
 | 
			
		||||
        return RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(!inheritanceDisabled).create();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleSetting setRuleSetting(String folderId, RuleSetting ruleSetting)
 | 
			
		||||
    {
 | 
			
		||||
        NodeRef folderNode = validator.validateFolderNode(folderId, true);
 | 
			
		||||
 | 
			
		||||
        switch (ruleSetting.getKey())
 | 
			
		||||
        {
 | 
			
		||||
            case IS_INHERITANCE_ENABLED_KEY:
 | 
			
		||||
                return updateIsInheritanceEnabled(folderNode, ruleSetting.getValue());
 | 
			
		||||
            default:
 | 
			
		||||
                throw new NotFoundException("Unrecognised rule setting key " + ruleSetting.getKey());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private RuleSetting updateIsInheritanceEnabled(NodeRef folderNode, Object value)
 | 
			
		||||
    {
 | 
			
		||||
        if (!(value instanceof Boolean))
 | 
			
		||||
        {
 | 
			
		||||
            throw new IllegalArgumentException("Rule setting " + IS_INHERITANCE_ENABLED_KEY + " requires a boolean value.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ((boolean) value)
 | 
			
		||||
        {
 | 
			
		||||
            nodeService.removeAspect(folderNode, ASPECT_IGNORE_INHERITED_RULES);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            nodeService.addAspect(folderNode, ASPECT_IGNORE_INHERITED_RULES, Collections.emptyMap());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(value).create();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setValidator(NodeValidator validator)
 | 
			
		||||
    {
 | 
			
		||||
        this.validator = validator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setNodeService(NodeService nodeService)
 | 
			
		||||
    {
 | 
			
		||||
        this.nodeService = nodeService;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.Nodes;
 | 
			
		||||
@@ -37,6 +38,7 @@ import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.ListPage;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.action.CompositeAction;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.rule.RuleService;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
@@ -50,47 +52,55 @@ public class RulesImpl implements Rules
 | 
			
		||||
    private Nodes nodes;
 | 
			
		||||
    private RuleService ruleService;
 | 
			
		||||
    private NodeValidator validator;
 | 
			
		||||
    private RuleLoader ruleLoader;
 | 
			
		||||
    private ActionParameterConverter actionParameterConverter;
 | 
			
		||||
    private ActionPermissionValidator actionPermissionValidator;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public CollectionWithPagingInfo<Rule> getRules(final String folderNodeId, final String ruleSetId, final Paging paging)
 | 
			
		||||
    public CollectionWithPagingInfo<Rule> getRules(final String folderNodeId,
 | 
			
		||||
                                                   final String ruleSetId,
 | 
			
		||||
                                                   final List<String> includes,
 | 
			
		||||
                                                   final Paging paging)
 | 
			
		||||
    {
 | 
			
		||||
        final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
 | 
			
		||||
        final NodeRef ruleSetNodeRef = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
 | 
			
		||||
        validator.validateRuleSetNode(ruleSetId, folderNodeRef);
 | 
			
		||||
 | 
			
		||||
        final boolean isShared = validator.isRuleSetNotNullAndShared(ruleSetNodeRef);
 | 
			
		||||
        final List<Rule> rules = ruleService.getRules(folderNodeRef).stream()
 | 
			
		||||
            .map(ruleModel -> Rule.from(ruleModel, isShared))
 | 
			
		||||
            .collect(Collectors.toList());
 | 
			
		||||
                .map(ruleModel -> loadRuleAndConvertActionParams(ruleModel, includes))
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
        return ListPage.of(rules, paging);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Rule getRuleById(final String folderNodeId, final String ruleSetId, final String ruleId)
 | 
			
		||||
    public Rule getRuleById(final String folderNodeId, final String ruleSetId, final String ruleId, final List<String> includes)
 | 
			
		||||
    {
 | 
			
		||||
        final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, false);
 | 
			
		||||
        final NodeRef ruleSetNodeRef = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
 | 
			
		||||
        final NodeRef ruleNodeRef = validator.validateRuleNode(ruleId, ruleSetNodeRef);
 | 
			
		||||
 | 
			
		||||
        return Rule.from(ruleService.getRule(ruleNodeRef), validator.isRuleSetNotNullAndShared(ruleSetNodeRef));
 | 
			
		||||
        return loadRuleAndConvertActionParams(ruleService.getRule(ruleNodeRef), includes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<Rule> createRules(final String folderNodeId, final String ruleSetId, final List<Rule> rules)
 | 
			
		||||
    public List<Rule> createRules(final String folderNodeId, final String ruleSetId, final List<Rule> rules, final List<String> includes)
 | 
			
		||||
    {
 | 
			
		||||
        final NodeRef folderNodeRef = validator.validateFolderNode(folderNodeId, true);
 | 
			
		||||
        // Don't validate the ruleset node if -default- is passed since we may need to create it.
 | 
			
		||||
        final NodeRef ruleSetNodeRef = (RuleSet.isNotDefaultId(ruleSetId)) ? validator.validateRuleSetNode(ruleSetId, folderNodeRef) : null;
 | 
			
		||||
        if (RuleSet.isNotDefaultId(ruleSetId))
 | 
			
		||||
        {
 | 
			
		||||
            validator.validateRuleSetNode(ruleSetId, folderNodeRef);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return rules.stream()
 | 
			
		||||
                    .map(rule -> rule.toServiceModel(nodes))
 | 
			
		||||
                    .map(rule -> ruleService.saveRule(folderNodeRef, rule))
 | 
			
		||||
                    .map(rule -> Rule.from(rule, validator.isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef)))
 | 
			
		||||
                    .collect(Collectors.toList());
 | 
			
		||||
                .map(this::mapToServiceModelAndValidateActions)
 | 
			
		||||
                .map(rule -> ruleService.saveRule(folderNodeRef, rule))
 | 
			
		||||
                .map(rule -> loadRuleAndConvertActionParams(rule, includes))
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule)
 | 
			
		||||
    public Rule updateRuleById(String folderNodeId, String ruleSetId, String ruleId, Rule rule, List<String> includes)
 | 
			
		||||
    {
 | 
			
		||||
        LOGGER.debug("Updating rule in folder {}, rule set {}, rule {} to {}", folderNodeId, ruleSetId, ruleId, rule);
 | 
			
		||||
 | 
			
		||||
@@ -98,8 +108,7 @@ public class RulesImpl implements Rules
 | 
			
		||||
        NodeRef ruleSetNodeRef = validator.validateRuleSetNode(ruleSetId, folderNodeRef);
 | 
			
		||||
        validator.validateRuleNode(ruleId, ruleSetNodeRef);
 | 
			
		||||
 | 
			
		||||
        boolean shared = validator.isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef);
 | 
			
		||||
        return Rule.from(ruleService.saveRule(folderNodeRef, rule.toServiceModel(nodes)), shared);
 | 
			
		||||
        return ruleLoader.loadRule(ruleService.saveRule(folderNodeRef, mapToServiceModelAndValidateActions(rule)), includes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -112,6 +121,30 @@ public class RulesImpl implements Rules
 | 
			
		||||
        ruleService.removeRule(folderNodeRef, rule);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private org.alfresco.service.cmr.rule.Rule mapToServiceModelAndValidateActions(Rule rule)
 | 
			
		||||
    {
 | 
			
		||||
        final org.alfresco.service.cmr.rule.Rule serviceModelRule = rule.toServiceModel(nodes);
 | 
			
		||||
        final CompositeAction compositeAction = (CompositeAction) serviceModelRule.getAction();
 | 
			
		||||
        compositeAction.getActions().forEach(action -> action.setParameterValues(
 | 
			
		||||
                actionParameterConverter.getConvertedParams(action.getParameterValues(), action.getActionDefinitionName())));
 | 
			
		||||
 | 
			
		||||
        return actionPermissionValidator.validateRulePermissions(serviceModelRule);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Rule loadRuleAndConvertActionParams(org.alfresco.service.cmr.rule.Rule ruleModel, List<String> includes)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        final Rule rule = ruleLoader.loadRule(ruleModel, includes);
 | 
			
		||||
        rule.getActions()
 | 
			
		||||
                .forEach(a -> a.setParams(a.getParams().entrySet()
 | 
			
		||||
                                .stream()
 | 
			
		||||
                                .collect(Collectors
 | 
			
		||||
                                        .toMap(Map.Entry::getKey, e -> actionParameterConverter.convertParamFromServiceModel(e.getValue())))
 | 
			
		||||
                        )
 | 
			
		||||
                );
 | 
			
		||||
        return rule;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setNodes(Nodes nodes)
 | 
			
		||||
    {
 | 
			
		||||
        this.nodes = nodes;
 | 
			
		||||
@@ -126,4 +159,19 @@ public class RulesImpl implements Rules
 | 
			
		||||
    {
 | 
			
		||||
        this.validator = validator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setRuleLoader(RuleLoader ruleLoader)
 | 
			
		||||
    {
 | 
			
		||||
        this.ruleLoader = ruleLoader;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setActionParameterConverter(ActionParameterConverter actionParameterConverter)
 | 
			
		||||
    {
 | 
			
		||||
        this.actionParameterConverter = actionParameterConverter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setActionPermissionValidator(ActionPermissionValidator actionPermissionValidator)
 | 
			
		||||
    {
 | 
			
		||||
        this.actionPermissionValidator = actionPermissionValidator;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,6 @@ import java.util.Objects;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.repo.action.ActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.CompositeActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.executer.SetPropertyValueActionExecuter;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.util.GUID;
 | 
			
		||||
@@ -75,7 +74,7 @@ public class Action
 | 
			
		||||
     */
 | 
			
		||||
    public org.alfresco.service.cmr.action.Action toServiceModel(final NodeRef nodeRef)
 | 
			
		||||
    {
 | 
			
		||||
        return new ActionImpl(nodeRef, GUID.generate(), SetPropertyValueActionExecuter.NAME, params);
 | 
			
		||||
        return new ActionImpl(nodeRef, GUID.generate(), this.actionDefinitionId, params);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,59 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.model.rules;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonValue;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
 | 
			
		||||
/** The reason why a rule set applies to a folder. */
 | 
			
		||||
@Experimental
 | 
			
		||||
public enum InclusionType
 | 
			
		||||
{
 | 
			
		||||
    OWNED, INHERITED, LINKED;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Load an InclusionType from a given string (case insensitively).
 | 
			
		||||
     *
 | 
			
		||||
     * @param inclusionType The given string.
 | 
			
		||||
     * @return The inclusion type.
 | 
			
		||||
     */
 | 
			
		||||
    public static InclusionType from(String inclusionType)
 | 
			
		||||
    {
 | 
			
		||||
        return InclusionType.valueOf(inclusionType.toUpperCase());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The lower case version of the inclusion type.
 | 
			
		||||
     *
 | 
			
		||||
     * @return A lowercase string.
 | 
			
		||||
     */
 | 
			
		||||
    @JsonValue
 | 
			
		||||
    public String toString()
 | 
			
		||||
    {
 | 
			
		||||
        return super.toString().toLowerCase();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -30,12 +30,14 @@ import java.util.List;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.repo.action.ActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.executer.ScriptActionExecuter;
 | 
			
		||||
import org.alfresco.rest.api.Nodes;
 | 
			
		||||
import org.alfresco.rest.framework.resource.UniqueId;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.action.CompositeAction;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.util.GUID;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
public class Rule
 | 
			
		||||
@@ -46,9 +48,9 @@ public class Rule
 | 
			
		||||
    private boolean enabled;
 | 
			
		||||
    private boolean cascade;
 | 
			
		||||
    private boolean asynchronous;
 | 
			
		||||
    private boolean shared;
 | 
			
		||||
    private Boolean isShared;
 | 
			
		||||
    private String errorScript;
 | 
			
		||||
    private List<RuleTrigger> triggers;
 | 
			
		||||
    private List<RuleTrigger> triggers = List.of(RuleTrigger.INBOUND);
 | 
			
		||||
    private CompositeCondition conditions;
 | 
			
		||||
    private List<Action> actions;
 | 
			
		||||
 | 
			
		||||
@@ -58,7 +60,7 @@ public class Rule
 | 
			
		||||
     * @param ruleModel - {@link org.alfresco.service.cmr.rule.Rule} service POJO
 | 
			
		||||
     * @return {@link Rule} REST model
 | 
			
		||||
     */
 | 
			
		||||
    public static Rule from(final org.alfresco.service.cmr.rule.Rule ruleModel, final boolean shared)
 | 
			
		||||
    public static Rule from(final org.alfresco.service.cmr.rule.Rule ruleModel)
 | 
			
		||||
    {
 | 
			
		||||
        if (ruleModel == null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -70,8 +72,7 @@ public class Rule
 | 
			
		||||
            .description(ruleModel.getDescription())
 | 
			
		||||
            .enabled(!ruleModel.getRuleDisabled())
 | 
			
		||||
            .cascade(ruleModel.isAppliedToChildren())
 | 
			
		||||
            .asynchronous(ruleModel.getExecuteAsynchronously())
 | 
			
		||||
            .shared(shared);
 | 
			
		||||
            .asynchronous(ruleModel.getExecuteAsynchronously());
 | 
			
		||||
 | 
			
		||||
        if (ruleModel.getNodeRef() != null) {
 | 
			
		||||
            builder.id(ruleModel.getNodeRef().getId());
 | 
			
		||||
@@ -108,8 +109,21 @@ public class Rule
 | 
			
		||||
        final NodeRef nodeRef = (id != null) ? nodes.validateOrLookupNode(id, null) : null;
 | 
			
		||||
        ruleModel.setNodeRef(nodeRef);
 | 
			
		||||
        ruleModel.setTitle(name);
 | 
			
		||||
 | 
			
		||||
        ruleModel.setDescription(description);
 | 
			
		||||
        ruleModel.setRuleDisabled(!enabled);
 | 
			
		||||
        ruleModel.applyToChildren(cascade);
 | 
			
		||||
        ruleModel.setExecuteAsynchronously(asynchronous);
 | 
			
		||||
        if (triggers != null)
 | 
			
		||||
        {
 | 
			
		||||
            ruleModel.setRuleTypes(triggers.stream().map(RuleTrigger::getValue).collect(Collectors.toList()));
 | 
			
		||||
        }
 | 
			
		||||
        ruleModel.setAction(Action.toCompositeAction(actions));
 | 
			
		||||
        if (errorScript != null)
 | 
			
		||||
        {
 | 
			
		||||
            final org.alfresco.service.cmr.action.Action compensatingAction = new ActionImpl(null, GUID.generate(), ScriptActionExecuter.NAME);
 | 
			
		||||
            compensatingAction.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, errorScript);
 | 
			
		||||
            ruleModel.getAction().setCompensatingAction(compensatingAction);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ruleModel;
 | 
			
		||||
    }
 | 
			
		||||
@@ -185,14 +199,14 @@ public class Rule
 | 
			
		||||
        this.errorScript = errorScript;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isShared()
 | 
			
		||||
    public Boolean isIsShared()
 | 
			
		||||
    {
 | 
			
		||||
        return shared;
 | 
			
		||||
        return isShared;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setShared(boolean shared)
 | 
			
		||||
    public void setIsShared(Boolean shared)
 | 
			
		||||
    {
 | 
			
		||||
        this.shared = shared;
 | 
			
		||||
        this.isShared = shared;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<String> getTriggers()
 | 
			
		||||
@@ -204,7 +218,15 @@ public class Rule
 | 
			
		||||
        return triggers.stream().map(RuleTrigger::getValue).collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setTriggers(List<RuleTrigger> triggers)
 | 
			
		||||
    public void setTriggers(List<String> triggers)
 | 
			
		||||
    {
 | 
			
		||||
        if (triggers != null)
 | 
			
		||||
        {
 | 
			
		||||
            this.triggers = triggers.stream().map(RuleTrigger::of).collect(Collectors.toList());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setRuleTriggers(List<RuleTrigger> triggers)
 | 
			
		||||
    {
 | 
			
		||||
        this.triggers = triggers;
 | 
			
		||||
    }
 | 
			
		||||
@@ -233,7 +255,7 @@ public class Rule
 | 
			
		||||
    public String toString()
 | 
			
		||||
    {
 | 
			
		||||
        return "Rule{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", description='" + description + '\'' + ", enabled=" + enabled + ", cascade=" + cascade
 | 
			
		||||
            + ", asynchronous=" + asynchronous + ", shared=" + shared + ", errorScript='" + errorScript + '\'' + ", triggers=" + triggers + ", conditions=" + conditions
 | 
			
		||||
            + ", asynchronous=" + asynchronous + ", isShared=" + isShared + ", errorScript='" + errorScript + '\'' + ", triggers=" + triggers + ", conditions=" + conditions
 | 
			
		||||
            + ", actions=" + actions + '}';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -245,15 +267,23 @@ public class Rule
 | 
			
		||||
        if (o == null || getClass() != o.getClass())
 | 
			
		||||
            return false;
 | 
			
		||||
        Rule rule = (Rule) o;
 | 
			
		||||
        return enabled == rule.enabled && cascade == rule.cascade && asynchronous == rule.asynchronous && shared == rule.shared && Objects.equals(id, rule.id) && Objects.equals(
 | 
			
		||||
            name, rule.name) && Objects.equals(description, rule.description) && Objects.equals(errorScript, rule.errorScript) && Objects.equals(triggers, rule.triggers)
 | 
			
		||||
            && Objects.equals(conditions, rule.conditions) && Objects.equals(actions, rule.actions);
 | 
			
		||||
        return enabled == rule.enabled
 | 
			
		||||
                && cascade == rule.cascade
 | 
			
		||||
                && asynchronous == rule.asynchronous
 | 
			
		||||
                && Objects.equals(isShared, rule.isShared)
 | 
			
		||||
                && Objects.equals(id, rule.id)
 | 
			
		||||
                && Objects.equals(name, rule.name)
 | 
			
		||||
                && Objects.equals(description, rule.description)
 | 
			
		||||
                && Objects.equals(errorScript, rule.errorScript)
 | 
			
		||||
                && Objects.equals(triggers, rule.triggers)
 | 
			
		||||
                && Objects.equals(conditions, rule.conditions)
 | 
			
		||||
                && Objects.equals(actions, rule.actions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int hashCode()
 | 
			
		||||
    {
 | 
			
		||||
        return Objects.hash(id, name, description, enabled, cascade, asynchronous, shared, errorScript, triggers, conditions, actions);
 | 
			
		||||
        return Objects.hash(id, name, description, enabled, cascade, asynchronous, isShared, errorScript, triggers, conditions, actions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Builder builder()
 | 
			
		||||
@@ -270,9 +300,9 @@ public class Rule
 | 
			
		||||
        private boolean enabled;
 | 
			
		||||
        private boolean cascade;
 | 
			
		||||
        private boolean asynchronous;
 | 
			
		||||
        private boolean shared;
 | 
			
		||||
        private Boolean isShared;
 | 
			
		||||
        private String errorScript;
 | 
			
		||||
        private List<RuleTrigger> triggers;
 | 
			
		||||
        private List<RuleTrigger> triggers = List.of(RuleTrigger.INBOUND);
 | 
			
		||||
        private CompositeCondition conditions;
 | 
			
		||||
        private List<Action> actions;
 | 
			
		||||
 | 
			
		||||
@@ -312,9 +342,9 @@ public class Rule
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Builder shared(boolean shared)
 | 
			
		||||
        public Builder isShared(Boolean isShared)
 | 
			
		||||
        {
 | 
			
		||||
            this.shared = shared;
 | 
			
		||||
            this.isShared = isShared;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -351,9 +381,9 @@ public class Rule
 | 
			
		||||
            rule.setEnabled(enabled);
 | 
			
		||||
            rule.setCascade(cascade);
 | 
			
		||||
            rule.setAsynchronous(asynchronous);
 | 
			
		||||
            rule.setShared(shared);
 | 
			
		||||
            rule.setIsShared(isShared);
 | 
			
		||||
            rule.setErrorScript(errorScript);
 | 
			
		||||
            rule.setTriggers(triggers);
 | 
			
		||||
            rule.setRuleTriggers(triggers);
 | 
			
		||||
            rule.setConditions(conditions);
 | 
			
		||||
            rule.setActions(actions);
 | 
			
		||||
            return rule;
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
package org.alfresco.rest.api.model.rules;
 | 
			
		||||
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.StringJoiner;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
@@ -38,6 +39,7 @@ public class RuleSet
 | 
			
		||||
 | 
			
		||||
    private String id;
 | 
			
		||||
    private NodeRef owningFolder;
 | 
			
		||||
    private InclusionType inclusionType;
 | 
			
		||||
 | 
			
		||||
    public static RuleSet of(String id)
 | 
			
		||||
    {
 | 
			
		||||
@@ -74,10 +76,26 @@ public class RuleSet
 | 
			
		||||
        this.owningFolder = owningFolder;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public InclusionType getInclusionType()
 | 
			
		||||
    {
 | 
			
		||||
        return inclusionType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setInclusionType(InclusionType inclusionType)
 | 
			
		||||
    {
 | 
			
		||||
        this.inclusionType = inclusionType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString()
 | 
			
		||||
    {
 | 
			
		||||
        return "RuleSet{" + "id='" + id + '\'' + '}';
 | 
			
		||||
        return "RuleSet{"
 | 
			
		||||
                + new StringJoiner(", ")
 | 
			
		||||
                    .add("id='" + id + "'")
 | 
			
		||||
                    .add("owningFolder='" + owningFolder + "'")
 | 
			
		||||
                    .add("inclusionType='" + inclusionType + "'")
 | 
			
		||||
                    .toString()
 | 
			
		||||
                + '}';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -89,13 +107,14 @@ public class RuleSet
 | 
			
		||||
            return false;
 | 
			
		||||
        RuleSet ruleSet = (RuleSet) o;
 | 
			
		||||
        return Objects.equals(id, ruleSet.id)
 | 
			
		||||
                && Objects.equals(owningFolder, ruleSet.owningFolder);
 | 
			
		||||
                && Objects.equals(owningFolder, ruleSet.owningFolder)
 | 
			
		||||
                && inclusionType == ruleSet.inclusionType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int hashCode()
 | 
			
		||||
    {
 | 
			
		||||
        return Objects.hash(id, owningFolder);
 | 
			
		||||
        return Objects.hash(id, owningFolder, inclusionType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Builder builder()
 | 
			
		||||
@@ -107,6 +126,7 @@ public class RuleSet
 | 
			
		||||
    {
 | 
			
		||||
        private String id;
 | 
			
		||||
        private NodeRef owningFolder;
 | 
			
		||||
        private InclusionType inclusionType;
 | 
			
		||||
 | 
			
		||||
        public Builder id(String id)
 | 
			
		||||
        {
 | 
			
		||||
@@ -120,11 +140,18 @@ public class RuleSet
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Builder inclusionType(InclusionType inclusionType)
 | 
			
		||||
        {
 | 
			
		||||
            this.inclusionType = inclusionType;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public RuleSet create()
 | 
			
		||||
        {
 | 
			
		||||
            final RuleSet ruleSet = new RuleSet();
 | 
			
		||||
            ruleSet.setId(id);
 | 
			
		||||
            ruleSet.setOwningFolder(owningFolder);
 | 
			
		||||
            ruleSet.setInclusionType(inclusionType);
 | 
			
		||||
            return ruleSet;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.model.rules;
 | 
			
		||||
 | 
			
		||||
public class RuleSetLink
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This id is referring to the node id of the linked-to-folder which contains the ruleset(s)
 | 
			
		||||
     */
 | 
			
		||||
    private String id;
 | 
			
		||||
 | 
			
		||||
    public void setId(String id)
 | 
			
		||||
    {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getId()
 | 
			
		||||
    {
 | 
			
		||||
        return id;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,126 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.model.rules;
 | 
			
		||||
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.StringJoiner;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.framework.resource.UniqueId;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
public class RuleSetting
 | 
			
		||||
{
 | 
			
		||||
    public static final String IS_INHERITANCE_ENABLED_KEY = "-isInheritanceEnabled-";
 | 
			
		||||
 | 
			
		||||
    private String key;
 | 
			
		||||
    private Object value;
 | 
			
		||||
 | 
			
		||||
    @UniqueId
 | 
			
		||||
    public String getKey()
 | 
			
		||||
    {
 | 
			
		||||
        return key;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setKey(String key)
 | 
			
		||||
    {
 | 
			
		||||
        this.key = key;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Object getValue()
 | 
			
		||||
    {
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setValue(Object value)
 | 
			
		||||
    {
 | 
			
		||||
        this.value = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString()
 | 
			
		||||
    {
 | 
			
		||||
        return "RuleSetting{"
 | 
			
		||||
                + new StringJoiner(", ")
 | 
			
		||||
                    .add("key=" + key)
 | 
			
		||||
                    .add("value=" + value.toString())
 | 
			
		||||
                    .toString()
 | 
			
		||||
                + "}";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals(Object o)
 | 
			
		||||
    {
 | 
			
		||||
        if (this == o)
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        if (!(o instanceof RuleSetting))
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        RuleSetting that = (RuleSetting) o;
 | 
			
		||||
        return Objects.equals(key, that.key)
 | 
			
		||||
                && Objects.equals(value, that.value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int hashCode()
 | 
			
		||||
    {
 | 
			
		||||
        return Objects.hash(key, value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RuleSetting.Builder builder()
 | 
			
		||||
    {
 | 
			
		||||
        return new RuleSetting.Builder();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class Builder
 | 
			
		||||
    {
 | 
			
		||||
        private String key;
 | 
			
		||||
        private Object value;
 | 
			
		||||
 | 
			
		||||
        public RuleSetting.Builder key(String key)
 | 
			
		||||
        {
 | 
			
		||||
            this.key = key;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public RuleSetting.Builder value(Object value)
 | 
			
		||||
        {
 | 
			
		||||
            this.value = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public RuleSetting create()
 | 
			
		||||
        {
 | 
			
		||||
            final RuleSetting ruleSetting = new RuleSetting();
 | 
			
		||||
            ruleSetting.setKey(key);
 | 
			
		||||
            ruleSetting.setValue(value);
 | 
			
		||||
            return ruleSetting;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,31 +31,15 @@ import org.alfresco.service.Experimental;
 | 
			
		||||
@Experimental
 | 
			
		||||
public enum RuleTrigger
 | 
			
		||||
{
 | 
			
		||||
    INBOUND("inbound"),
 | 
			
		||||
    UPDATE("update"),
 | 
			
		||||
    OUTBOUND("outbound");
 | 
			
		||||
 | 
			
		||||
    RuleTrigger(String value)
 | 
			
		||||
    {
 | 
			
		||||
        this.value = value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final String value;
 | 
			
		||||
    INBOUND, UPDATE, OUTBOUND;
 | 
			
		||||
 | 
			
		||||
    public String getValue()
 | 
			
		||||
    {
 | 
			
		||||
        return value;
 | 
			
		||||
        return this.name().toLowerCase();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static RuleTrigger of(final String value)
 | 
			
		||||
    {
 | 
			
		||||
        for (RuleTrigger ruleTrigger : values())
 | 
			
		||||
        {
 | 
			
		||||
            if (ruleTrigger.value.equals(value)) {
 | 
			
		||||
                return ruleTrigger;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
        return RuleTrigger.valueOf(value.toUpperCase());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.nodes;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.RuleSets;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSetLink;
 | 
			
		||||
import org.alfresco.rest.framework.WebApiDescription;
 | 
			
		||||
import org.alfresco.rest.framework.WebApiParam;
 | 
			
		||||
import org.alfresco.rest.framework.core.ResourceParameter;
 | 
			
		||||
import org.alfresco.rest.framework.resource.RelationshipResource;
 | 
			
		||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
 | 
			
		||||
import org.alfresco.util.PropertyCheck;
 | 
			
		||||
import org.springframework.beans.factory.InitializingBean;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@RelationshipResource(name = "rule-set-links", entityResource = NodesEntityResource.class, title = "Linking to a rule set")
 | 
			
		||||
public class NodeRuleSetLinksRelation implements InitializingBean, RelationshipResourceAction.Create<RuleSetLink>
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    private final RuleSets ruleSets;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void afterPropertiesSet() throws Exception
 | 
			
		||||
    {
 | 
			
		||||
        PropertyCheck.mandatory(this, "ruleSets", ruleSets);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @WebApiParam(name = "ruleSetLinkRequest", title = "Request body - rule set id",
 | 
			
		||||
            description = "Request body with rule set id", kind = ResourceParameter.KIND.HTTP_BODY_OBJECT)
 | 
			
		||||
    @WebApiDescription(title = "Link a rule set to a folder node",
 | 
			
		||||
            description = "Submits a request to link a rule set to folder",
 | 
			
		||||
            successStatus = HttpServletResponse.SC_CREATED)
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<RuleSetLink> create(String nodeId, List<RuleSetLink> ruleSetLinksBody, Parameters parameters)
 | 
			
		||||
    {
 | 
			
		||||
        return ruleSetLinksBody.stream()
 | 
			
		||||
                .map(r -> ruleSets.linkToRuleSet(nodeId, r.getId()))
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public NodeRuleSetLinksRelation(RuleSets ruleSets)
 | 
			
		||||
    {
 | 
			
		||||
        this.ruleSets = ruleSets;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,104 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.nodes;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.RuleSettings;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSetting;
 | 
			
		||||
import org.alfresco.rest.framework.WebApiDescription;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
 | 
			
		||||
import org.alfresco.rest.framework.resource.RelationshipResource;
 | 
			
		||||
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.util.PropertyCheck;
 | 
			
		||||
import org.springframework.beans.factory.InitializingBean;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Folder node rule settings (rule inheritance).
 | 
			
		||||
 */
 | 
			
		||||
@Experimental
 | 
			
		||||
@RelationshipResource (name = "rule-settings", entityResource = NodesEntityResource.class, title = "Folder rule settings")
 | 
			
		||||
public class NodeRuleSettingsRelation implements RelationshipResourceAction.ReadById<RuleSetting>,
 | 
			
		||||
                                                 RelationshipResourceAction.Update<RuleSetting>,
 | 
			
		||||
                                                 InitializingBean
 | 
			
		||||
{
 | 
			
		||||
    private RuleSettings ruleSettings;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void afterPropertiesSet() throws Exception
 | 
			
		||||
    {
 | 
			
		||||
        PropertyCheck.mandatory(this, "ruleSettings", ruleSettings);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the given configuration value for the specified folder.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * - GET /nodes/{folderId}/rule-settings/{ruleSettingKey}
 | 
			
		||||
     *
 | 
			
		||||
     * @param folderId The id of the folder.
 | 
			
		||||
     * @param ruleSettingKey The setting to retrieve.
 | 
			
		||||
     * @param parameters Unused.
 | 
			
		||||
     * @return {@link RuleSetting} The current value of the setting.
 | 
			
		||||
     */
 | 
			
		||||
    @WebApiDescription (
 | 
			
		||||
            title = "Get a folder node rule setting",
 | 
			
		||||
            description = "Returns the specified rule setting for the given folder",
 | 
			
		||||
            successStatus = HttpServletResponse.SC_OK
 | 
			
		||||
    )
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleSetting readById(String folderId, String ruleSettingKey, Parameters parameters) throws RelationshipResourceNotFoundException
 | 
			
		||||
    {
 | 
			
		||||
        return ruleSettings.getRuleSetting(folderId, ruleSettingKey);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the value of a rule setting for the specified folder.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * PUT /nodes/{folderId}/rule-settings/{ruleSettingKey}
 | 
			
		||||
     *
 | 
			
		||||
     * @param folderId The id of the folder.
 | 
			
		||||
     * @param ruleSetting The new value of the rule setting.
 | 
			
		||||
     * @param parameters Unused.
 | 
			
		||||
     * @return The updated rule setting.
 | 
			
		||||
     */
 | 
			
		||||
    @WebApiDescription (
 | 
			
		||||
            title = "Update folder node rule setting",
 | 
			
		||||
            description = "Update a rule setting for given node",
 | 
			
		||||
            successStatus = HttpServletResponse.SC_OK
 | 
			
		||||
    )
 | 
			
		||||
    @Override
 | 
			
		||||
    public RuleSetting update(String folderId, RuleSetting ruleSetting, Parameters parameters)
 | 
			
		||||
    {
 | 
			
		||||
        return ruleSettings.setRuleSetting(folderId, ruleSetting);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setRuleSettings(RuleSettings ruleSettings)
 | 
			
		||||
    {
 | 
			
		||||
        this.ruleSettings = ruleSettings;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -26,6 +26,9 @@
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.nodes;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.Rules;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Rule;
 | 
			
		||||
import org.alfresco.rest.framework.WebApiDescription;
 | 
			
		||||
@@ -38,9 +41,6 @@ import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.util.PropertyCheck;
 | 
			
		||||
import org.springframework.beans.factory.InitializingBean;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Folder node's rules.
 | 
			
		||||
 *
 | 
			
		||||
@@ -82,7 +82,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
 | 
			
		||||
    {
 | 
			
		||||
        final String ruleSetId = parameters.getRelationshipId();
 | 
			
		||||
 | 
			
		||||
        return rules.getRules(folderNodeId, ruleSetId, parameters.getPaging());
 | 
			
		||||
        return rules.getRules(folderNodeId, ruleSetId, parameters.getInclude(), parameters.getPaging());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -106,7 +106,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
 | 
			
		||||
    {
 | 
			
		||||
        final String ruleId = parameters.getRelationship2Id();
 | 
			
		||||
 | 
			
		||||
        return rules.getRuleById(folderNodeId, ruleSetId, ruleId);
 | 
			
		||||
        return rules.getRuleById(folderNodeId, ruleSetId, ruleId, parameters.getInclude());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -129,7 +129,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
 | 
			
		||||
    {
 | 
			
		||||
        final String ruleSetId = parameters.getRelationshipId();
 | 
			
		||||
 | 
			
		||||
        return rules.createRules(folderNodeId, ruleSetId, ruleList);
 | 
			
		||||
        return rules.createRules(folderNodeId, ruleSetId, ruleList, parameters.getInclude());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -153,7 +153,7 @@ public class NodeRulesRelation implements RelationshipResourceAction.Read<Rule>,
 | 
			
		||||
    {
 | 
			
		||||
        String ruleSetId = parameters.getRelationshipId();
 | 
			
		||||
        String ruleId = parameters.getRelationship2Id();
 | 
			
		||||
        return rules.updateRuleById(folderNodeId, ruleSetId, ruleId, rule);
 | 
			
		||||
        return rules.updateRuleById(folderNodeId, ruleSetId, ruleId, rule, parameters.getInclude());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -854,6 +854,7 @@
 | 
			
		||||
        <property name="nodes" ref="Nodes" />
 | 
			
		||||
        <property name="permissionService" ref="PermissionService" />
 | 
			
		||||
        <property name="ruleService" ref="RuleService" />
 | 
			
		||||
        <property name="nodeService" ref="NodeService"/>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean class="org.alfresco.rest.api.nodes.NodeRulesRelation">
 | 
			
		||||
@@ -868,6 +869,8 @@
 | 
			
		||||
        <property name="ruleSetLoader" ref="ruleSetLoader" />
 | 
			
		||||
        <property name="validator" ref="nodeValidator" />
 | 
			
		||||
        <property name="ruleService" ref="RuleService" />
 | 
			
		||||
        <property name="nodeService" ref="NodeService"/>
 | 
			
		||||
        <property name="runtimeRuleService" ref="ruleService"/>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="RuleSets" class="org.springframework.aop.framework.ProxyFactoryBean">
 | 
			
		||||
@@ -880,14 +883,32 @@
 | 
			
		||||
        </property>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="ruleLoader" class="org.alfresco.rest.api.impl.rules.RuleLoader">
 | 
			
		||||
        <property name="ruleService" ref="RuleService" />
 | 
			
		||||
        <property name="nodeValidator" ref="nodeValidator" />
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean class="org.alfresco.rest.api.nodes.NodeRuleSetsRelation">
 | 
			
		||||
        <property name="ruleSets" ref="RuleSets" />
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="actionParameterConverter" class="org.alfresco.rest.api.impl.rules.ActionParameterConverter">
 | 
			
		||||
        <constructor-arg name="actionService" ref="ActionService"/>
 | 
			
		||||
        <constructor-arg name="dictionaryService" ref="DictionaryService"/>
 | 
			
		||||
        <constructor-arg name="namespaceService" ref="NamespaceService"/>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="actionPermissionValidator" class="org.alfresco.rest.api.impl.rules.ActionPermissionValidator">
 | 
			
		||||
        <constructor-arg name="runtimeActionService" ref="actionService"/>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="rules" class="org.alfresco.rest.api.impl.rules.RulesImpl">
 | 
			
		||||
        <property name="nodes" ref="Nodes" />
 | 
			
		||||
        <property name="validator" ref="nodeValidator"/>
 | 
			
		||||
        <property name="ruleService" ref="RuleService" />
 | 
			
		||||
        <property name="ruleLoader" ref="ruleLoader"/>
 | 
			
		||||
        <property name="actionParameterConverter" ref="actionParameterConverter"/>
 | 
			
		||||
        <property name="actionPermissionValidator" ref="actionPermissionValidator"/>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="Rules" class="org.springframework.aop.framework.ProxyFactoryBean">
 | 
			
		||||
@@ -900,6 +921,29 @@
 | 
			
		||||
        </property>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean class="org.alfresco.rest.api.nodes.NodeRuleSetLinksRelation">
 | 
			
		||||
        <constructor-arg name="ruleSets" ref="RuleSets" />
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="ruleSettings" class="org.alfresco.rest.api.impl.rules.RuleSettingsImpl">
 | 
			
		||||
        <property name="validator" ref="nodeValidator" />
 | 
			
		||||
        <property name="nodeService" ref="NodeService" />
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="RuleSettings" class="org.springframework.aop.framework.ProxyFactoryBean">
 | 
			
		||||
        <property name="proxyInterfaces" value="org.alfresco.rest.api.RuleSettings" />
 | 
			
		||||
        <property name="target" ref="ruleSettings" />
 | 
			
		||||
        <property name="interceptorNames">
 | 
			
		||||
            <list>
 | 
			
		||||
                <idref bean="legacyExceptionInterceptor" />
 | 
			
		||||
            </list>
 | 
			
		||||
        </property>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean class="org.alfresco.rest.api.nodes.NodeRuleSettingsRelation">
 | 
			
		||||
        <property name="ruleSettings" ref="RuleSettings" />
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean id="publicapi.mimeTypePropertyLookup" class="org.alfresco.rest.api.lookups.MimeTypePropertyLookup">
 | 
			
		||||
        <property name="serviceRegistry" ref="ServiceRegistry"/>
 | 
			
		||||
        <property name="supported">
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Share Services AMP
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software. 
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of 
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
package org.alfresco.rest.api;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.impl.rules.NodeValidatorTest;
 | 
			
		||||
import org.alfresco.rest.api.impl.rules.RuleSetsImplTest;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.ActionTest;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.CompositeConditionTest;
 | 
			
		||||
import org.alfresco.rest.api.impl.rules.RulesImplTest;
 | 
			
		||||
@@ -42,6 +43,7 @@ import org.junit.runners.Suite;
 | 
			
		||||
@Suite.SuiteClasses({
 | 
			
		||||
    NodeRulesRelationTest.class,
 | 
			
		||||
    RulesImplTest.class,
 | 
			
		||||
    RuleSetsImplTest.class,
 | 
			
		||||
    NodeValidatorTest.class,
 | 
			
		||||
    RuleTest.class,
 | 
			
		||||
    ActionTest.class,
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,592 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assert.assertTrue;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.any;
 | 
			
		||||
import static org.mockito.BDDMockito.given;
 | 
			
		||||
import static org.mockito.BDDMockito.then;
 | 
			
		||||
import static org.mockito.Mockito.times;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.repo.action.executer.AddFeaturesActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.CheckInActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.CopyActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.LinkCategoryActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.MoveActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.RemoveFeaturesActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.ScriptActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.SetPropertyValueActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.SimpleWorkflowActionExecuter;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.action.ActionDefinition;
 | 
			
		||||
import org.alfresco.service.cmr.action.ActionService;
 | 
			
		||||
import org.alfresco.service.cmr.action.ParameterDefinition;
 | 
			
		||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
 | 
			
		||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.namespace.NamespaceService;
 | 
			
		||||
import org.alfresco.service.namespace.QName;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.InjectMocks;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
@RunWith(MockitoJUnitRunner.class)
 | 
			
		||||
public class ActionParameterConverterTest
 | 
			
		||||
{
 | 
			
		||||
    private static final String VERSIONABLE = "versionable";
 | 
			
		||||
    private static final String VERSIONABLE_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + VERSIONABLE;
 | 
			
		||||
    private static final String CHECKOUT = "checkout";
 | 
			
		||||
    private static final String CHECKOUT_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + CHECKOUT;
 | 
			
		||||
    private static final String CONTAINS = "contains";
 | 
			
		||||
    private static final String CONTAINS_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + CONTAINS;
 | 
			
		||||
    private static final String CLASSIFIABLE = "generalclassifiable";
 | 
			
		||||
    private static final String CLASSIFIABLE_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + CLASSIFIABLE;
 | 
			
		||||
    private static final String IDENTIFIER = "identifier";
 | 
			
		||||
    private static final String IDENTIFIER_ASPECT = NamespaceService.CONTENT_MODEL_PREFIX + QName.NAMESPACE_PREFIX + IDENTIFIER;
 | 
			
		||||
 | 
			
		||||
    private static final String DUMMY_FOLDER_NODE_ID = "dummy-folder-node";
 | 
			
		||||
    private static final String DUMMY_SCRIPT_NODE_ID = "dummy-script-ref";
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private DictionaryService dictionaryService;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ActionService actionService;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private NamespaceService namespaceService;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ActionDefinition actionDefinition;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ParameterDefinition actionDefinitionParam1;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ParameterDefinition actionDefinitionParam2;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ParameterDefinition actionDefinitionParam3;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private DataTypeDefinition dataTypeDefinition1;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private DataTypeDefinition dataTypeDefinition2;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private DataTypeDefinition dataTypeDefinition3;
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private ActionParameterConverter objectUnderTest;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAddAspectConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = AddFeaturesActionExecuter.NAME;
 | 
			
		||||
        final String aspectNameKey = AddFeaturesActionExecuter.PARAM_ASPECT_NAME;
 | 
			
		||||
        final Map<String, Serializable> params = Map.of(aspectNameKey, VERSIONABLE_ASPECT);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(aspectNameKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        final QName qname = DataTypeDefinition.QNAME;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(qname);
 | 
			
		||||
        given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition1);
 | 
			
		||||
        given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(aspectNameKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should().getDataType(qname);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).should().getNamespaceURI(any());
 | 
			
		||||
        then(namespaceService).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedParam = convertedParams.get(aspectNameKey);
 | 
			
		||||
        assertTrue(convertedParam instanceof QName);
 | 
			
		||||
        assertEquals(VERSIONABLE, ((QName) convertedParam).getLocalName());
 | 
			
		||||
        assertEquals(VERSIONABLE_ASPECT, ((QName) convertedParam).getPrefixString());
 | 
			
		||||
        assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedParam).getNamespaceURI());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCopyConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = CopyActionExecuter.NAME;
 | 
			
		||||
        final String destinationFolderKey = CopyActionExecuter.PARAM_DESTINATION_FOLDER;
 | 
			
		||||
        final String deepCopyKey = CopyActionExecuter.PARAM_DEEP_COPY;
 | 
			
		||||
        final Map<String, Serializable> params = Map.of(destinationFolderKey, DUMMY_FOLDER_NODE_ID, deepCopyKey, true);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(destinationFolderKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(deepCopyKey)).willReturn(actionDefinitionParam2);
 | 
			
		||||
        final QName nodeRef = DataTypeDefinition.NODE_REF;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(nodeRef);
 | 
			
		||||
        final QName bool = DataTypeDefinition.BOOLEAN;
 | 
			
		||||
        given(actionDefinitionParam2.getType()).willReturn(bool);
 | 
			
		||||
 | 
			
		||||
        given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
 | 
			
		||||
        given(dictionaryService.getDataType(bool)).willReturn(dataTypeDefinition2);
 | 
			
		||||
        given(dataTypeDefinition2.getJavaClassName()).willReturn(Boolean.class.getName());
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(destinationFolderKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(deepCopyKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should(times(2)).getDataType(bool);
 | 
			
		||||
        then(dictionaryService).should().getDataType(nodeRef);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).shouldHaveNoInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedCopyParam = convertedParams.get(destinationFolderKey);
 | 
			
		||||
        assertTrue(convertedCopyParam instanceof NodeRef);
 | 
			
		||||
        assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedCopyParam).getStoreRef());
 | 
			
		||||
        assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedCopyParam).getId());
 | 
			
		||||
        final Serializable convertedDeepCopyParam = convertedParams.get(deepCopyKey);
 | 
			
		||||
        assertThat(convertedDeepCopyParam instanceof Boolean).isTrue();
 | 
			
		||||
        assertTrue(((Boolean) convertedDeepCopyParam));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExecuteScriptConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = ScriptActionExecuter.NAME;
 | 
			
		||||
        final String executeScriptKey = ScriptActionExecuter.PARAM_SCRIPTREF;
 | 
			
		||||
        final Map<String, Serializable> params = Map.of(executeScriptKey, DUMMY_SCRIPT_NODE_ID);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(executeScriptKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        final QName scriptNodeRef = DataTypeDefinition.NODE_REF;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(scriptNodeRef);
 | 
			
		||||
 | 
			
		||||
        given(dictionaryService.getDataType(scriptNodeRef)).willReturn(dataTypeDefinition1);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(executeScriptKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should().getDataType(scriptNodeRef);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).shouldHaveNoInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedCopyParam = convertedParams.get(executeScriptKey);
 | 
			
		||||
        assertTrue(convertedCopyParam instanceof NodeRef);
 | 
			
		||||
        assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedCopyParam).getStoreRef());
 | 
			
		||||
        assertEquals(DUMMY_SCRIPT_NODE_ID, ((NodeRef) convertedCopyParam).getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testMoveConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = MoveActionExecuter.NAME;
 | 
			
		||||
        final String destinationFolderKey = MoveActionExecuter.PARAM_DESTINATION_FOLDER;
 | 
			
		||||
        final Map<String, Serializable> params = Map.of(destinationFolderKey, DUMMY_FOLDER_NODE_ID);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(destinationFolderKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        final QName nodeRef = DataTypeDefinition.NODE_REF;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(nodeRef);
 | 
			
		||||
 | 
			
		||||
        given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(destinationFolderKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should().getDataType(nodeRef);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).shouldHaveNoInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedCopyParam = convertedParams.get(destinationFolderKey);
 | 
			
		||||
        assertTrue(convertedCopyParam instanceof NodeRef);
 | 
			
		||||
        assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedCopyParam).getStoreRef());
 | 
			
		||||
        assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedCopyParam).getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCheckInConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = CheckInActionExecuter.NAME;
 | 
			
		||||
        final String descriptionKey = CheckInActionExecuter.PARAM_DESCRIPTION;
 | 
			
		||||
        final String minorChangeKey = CheckInActionExecuter.PARAM_MINOR_CHANGE;
 | 
			
		||||
        String description = "dummy description";
 | 
			
		||||
        final Map<String, Serializable> params = Map.of(descriptionKey, description, minorChangeKey, true);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(descriptionKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(minorChangeKey)).willReturn(actionDefinitionParam2);
 | 
			
		||||
        final QName text = DataTypeDefinition.TEXT;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(text);
 | 
			
		||||
        final QName bool = DataTypeDefinition.BOOLEAN;
 | 
			
		||||
        given(actionDefinitionParam2.getType()).willReturn(bool);
 | 
			
		||||
 | 
			
		||||
        given(dictionaryService.getDataType(text)).willReturn(dataTypeDefinition1);
 | 
			
		||||
        given(dataTypeDefinition1.getJavaClassName()).willReturn(String.class.getName());
 | 
			
		||||
        given(dictionaryService.getDataType(bool)).willReturn(dataTypeDefinition2);
 | 
			
		||||
        given(dataTypeDefinition2.getJavaClassName()).willReturn(Boolean.class.getName());
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(descriptionKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(minorChangeKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should(times(2)).getDataType(bool);
 | 
			
		||||
        then(dictionaryService).should(times(2)).getDataType(text);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).shouldHaveNoInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedDescriptionParam = convertedParams.get(descriptionKey);
 | 
			
		||||
        assertTrue(convertedDescriptionParam instanceof String);
 | 
			
		||||
        assertEquals(description, convertedDescriptionParam);
 | 
			
		||||
        final Serializable convertedMinorChangeParam = convertedParams.get(minorChangeKey);
 | 
			
		||||
        assertTrue(convertedMinorChangeParam instanceof Boolean);
 | 
			
		||||
        assertTrue((Boolean) convertedMinorChangeParam);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCheckOutConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = CheckOutActionExecuter.NAME;
 | 
			
		||||
        final String destinationFolderKey = CheckOutActionExecuter.PARAM_DESTINATION_FOLDER;
 | 
			
		||||
        final String assocNameKey = CheckOutActionExecuter.PARAM_ASSOC_QNAME;
 | 
			
		||||
        final String assocTypeKey = CheckOutActionExecuter.PARAM_ASSOC_TYPE_QNAME;
 | 
			
		||||
        final Map<String, Serializable> params =
 | 
			
		||||
                Map.of(destinationFolderKey, DUMMY_FOLDER_NODE_ID, assocNameKey, CHECKOUT_ASPECT, assocTypeKey, CONTAINS_ASPECT);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(destinationFolderKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        final QName nodeRef = DataTypeDefinition.NODE_REF;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(nodeRef);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(assocNameKey)).willReturn(actionDefinitionParam2);
 | 
			
		||||
        final QName qname = DataTypeDefinition.QNAME;
 | 
			
		||||
        given(actionDefinitionParam2.getType()).willReturn(qname);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(assocTypeKey)).willReturn(actionDefinitionParam3);
 | 
			
		||||
        given(actionDefinitionParam3.getType()).willReturn(qname);
 | 
			
		||||
 | 
			
		||||
        given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
 | 
			
		||||
        given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition2);
 | 
			
		||||
        given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(destinationFolderKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(assocNameKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(assocTypeKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should(times(2)).getDataType(qname);
 | 
			
		||||
        then(dictionaryService).should().getDataType(nodeRef);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).should(times(2)).getNamespaceURI(any());
 | 
			
		||||
        then(namespaceService).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedDestinationParam = convertedParams.get(destinationFolderKey);
 | 
			
		||||
        assertTrue(convertedDestinationParam instanceof NodeRef);
 | 
			
		||||
        assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedDestinationParam).getStoreRef());
 | 
			
		||||
        assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedDestinationParam).getId());
 | 
			
		||||
        final Serializable convertedAssocNameParam = convertedParams.get(assocNameKey);
 | 
			
		||||
        assertTrue(convertedAssocNameParam instanceof QName);
 | 
			
		||||
        assertEquals(CHECKOUT, ((QName) convertedAssocNameParam).getLocalName());
 | 
			
		||||
        assertEquals(CHECKOUT_ASPECT, ((QName) convertedAssocNameParam).getPrefixString());
 | 
			
		||||
        assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedAssocNameParam).getNamespaceURI());
 | 
			
		||||
        final Serializable convertedAssocTypeParam = convertedParams.get(assocTypeKey);
 | 
			
		||||
        assertTrue(convertedAssocTypeParam instanceof QName);
 | 
			
		||||
        assertEquals(CONTAINS, ((QName) convertedAssocTypeParam).getLocalName());
 | 
			
		||||
        assertEquals(CONTAINS_ASPECT, ((QName) convertedAssocTypeParam).getPrefixString());
 | 
			
		||||
        assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedAssocTypeParam).getNamespaceURI());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCategoryLinkConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = LinkCategoryActionExecuter.NAME;
 | 
			
		||||
        final String categoryAspectKey = LinkCategoryActionExecuter.PARAM_CATEGORY_ASPECT;
 | 
			
		||||
        final String categoryValueKey = LinkCategoryActionExecuter.PARAM_CATEGORY_VALUE;
 | 
			
		||||
        final Map<String, Serializable> params = Map.of(categoryAspectKey, CLASSIFIABLE_ASPECT, categoryValueKey, DUMMY_FOLDER_NODE_ID);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(categoryAspectKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        final QName qname = DataTypeDefinition.QNAME;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(qname);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(categoryValueKey)).willReturn(actionDefinitionParam2);
 | 
			
		||||
        final QName nodeRef = DataTypeDefinition.NODE_REF;
 | 
			
		||||
        given(actionDefinitionParam2.getType()).willReturn(nodeRef);
 | 
			
		||||
 | 
			
		||||
        given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
 | 
			
		||||
        given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition2);
 | 
			
		||||
        given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(categoryAspectKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(categoryValueKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should().getDataType(qname);
 | 
			
		||||
        then(dictionaryService).should().getDataType(nodeRef);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).should().getNamespaceURI(any());
 | 
			
		||||
        then(namespaceService).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedCatValueParam = convertedParams.get(categoryAspectKey);
 | 
			
		||||
        assertTrue(convertedCatValueParam instanceof QName);
 | 
			
		||||
        assertEquals(CLASSIFIABLE, ((QName) convertedCatValueParam).getLocalName());
 | 
			
		||||
        assertEquals(CLASSIFIABLE_ASPECT, ((QName) convertedCatValueParam).getPrefixString());
 | 
			
		||||
        assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedCatValueParam).getNamespaceURI());
 | 
			
		||||
        final Serializable convertedDestinationParam = convertedParams.get(categoryValueKey);
 | 
			
		||||
        assertTrue(convertedDestinationParam instanceof NodeRef);
 | 
			
		||||
        assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedDestinationParam).getStoreRef());
 | 
			
		||||
        assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedDestinationParam).getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testRemoveAspectConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = RemoveFeaturesActionExecuter.NAME;
 | 
			
		||||
        final String aspectNameKey = RemoveFeaturesActionExecuter.PARAM_ASPECT_NAME;
 | 
			
		||||
        final Map<String, Serializable> params = Map.of(aspectNameKey, VERSIONABLE_ASPECT);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(aspectNameKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        final QName qname = DataTypeDefinition.QNAME;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(qname);
 | 
			
		||||
        given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition1);
 | 
			
		||||
        given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(aspectNameKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should().getDataType(qname);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).should().getNamespaceURI(any());
 | 
			
		||||
        then(namespaceService).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedParam = convertedParams.get(aspectNameKey);
 | 
			
		||||
        assertTrue(convertedParam instanceof QName);
 | 
			
		||||
        assertEquals(VERSIONABLE, ((QName) convertedParam).getLocalName());
 | 
			
		||||
        assertEquals(VERSIONABLE_ASPECT, ((QName) convertedParam).getPrefixString());
 | 
			
		||||
        assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedParam).getNamespaceURI());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testAddWorkflowConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = SimpleWorkflowActionExecuter.NAME;
 | 
			
		||||
        final String approveStepKey = SimpleWorkflowActionExecuter.PARAM_APPROVE_STEP;
 | 
			
		||||
        final String approveFolderKey = SimpleWorkflowActionExecuter.PARAM_APPROVE_FOLDER;
 | 
			
		||||
        final String approveMoveKey = SimpleWorkflowActionExecuter.PARAM_APPROVE_MOVE;
 | 
			
		||||
        final String rejectStepKey = SimpleWorkflowActionExecuter.PARAM_REJECT_STEP;
 | 
			
		||||
        final String rejectFolderKey = SimpleWorkflowActionExecuter.PARAM_REJECT_FOLDER;
 | 
			
		||||
        final String rejectMoveKey = SimpleWorkflowActionExecuter.PARAM_REJECT_MOVE;
 | 
			
		||||
        final String approve = "Approve";
 | 
			
		||||
        final String reject = "Reject";
 | 
			
		||||
        final Map<String, Serializable> params =
 | 
			
		||||
                Map.of(approveStepKey, approve, approveFolderKey, DUMMY_FOLDER_NODE_ID, approveMoveKey, true,
 | 
			
		||||
                        rejectStepKey, reject, rejectFolderKey, DUMMY_FOLDER_NODE_ID, rejectMoveKey, true);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(rejectStepKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(approveStepKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        final QName text = DataTypeDefinition.TEXT;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(text, text);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(rejectFolderKey)).willReturn(actionDefinitionParam2);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(approveFolderKey)).willReturn(actionDefinitionParam2);
 | 
			
		||||
        final QName nodeRef = DataTypeDefinition.NODE_REF;
 | 
			
		||||
        given(actionDefinitionParam2.getType()).willReturn(nodeRef, nodeRef);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(rejectMoveKey)).willReturn(actionDefinitionParam3);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(approveMoveKey)).willReturn(actionDefinitionParam3);
 | 
			
		||||
        final QName bool = DataTypeDefinition.BOOLEAN;
 | 
			
		||||
        given(actionDefinitionParam3.getType()).willReturn(bool, bool);
 | 
			
		||||
 | 
			
		||||
        given(dictionaryService.getDataType(nodeRef)).willReturn(dataTypeDefinition1);
 | 
			
		||||
        given(dictionaryService.getDataType(text)).willReturn(dataTypeDefinition2);
 | 
			
		||||
        given(dataTypeDefinition2.getJavaClassName()).willReturn(String.class.getName());
 | 
			
		||||
        given(dictionaryService.getDataType(bool)).willReturn(dataTypeDefinition3);
 | 
			
		||||
        given(dataTypeDefinition3.getJavaClassName()).willReturn(Boolean.class.getName());
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(approveStepKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(approveFolderKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(approveMoveKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(rejectStepKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(rejectFolderKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(rejectMoveKey);
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should(times(4)).getDataType(text);
 | 
			
		||||
        then(dictionaryService).should(times(2)).getDataType(nodeRef);
 | 
			
		||||
        then(dictionaryService).should(times(4)).getDataType(bool);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).shouldHaveNoInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedApproveStepParam = convertedParams.get(approveStepKey);
 | 
			
		||||
        assertTrue(convertedApproveStepParam instanceof String);
 | 
			
		||||
        assertEquals(approve, convertedApproveStepParam);
 | 
			
		||||
        final Serializable convertedRejectStepParam = convertedParams.get(rejectStepKey);
 | 
			
		||||
        assertTrue(convertedRejectStepParam instanceof String);
 | 
			
		||||
        assertEquals(reject, convertedRejectStepParam);
 | 
			
		||||
        final Serializable convertedApproveFolderParam = convertedParams.get(approveFolderKey);
 | 
			
		||||
        assertTrue(convertedApproveFolderParam instanceof NodeRef);
 | 
			
		||||
        assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedApproveFolderParam).getStoreRef());
 | 
			
		||||
        assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedApproveFolderParam).getId());
 | 
			
		||||
        final Serializable convertedRejectFolderParam = convertedParams.get(rejectFolderKey);
 | 
			
		||||
        assertTrue(convertedRejectFolderParam instanceof NodeRef);
 | 
			
		||||
        assertEquals(STORE_REF_WORKSPACE_SPACESSTORE, ((NodeRef) convertedRejectFolderParam).getStoreRef());
 | 
			
		||||
        assertEquals(DUMMY_FOLDER_NODE_ID, ((NodeRef) convertedRejectFolderParam).getId());
 | 
			
		||||
        final Serializable convertedApproveMoveParam = convertedParams.get(approveMoveKey);
 | 
			
		||||
        assertTrue(convertedApproveMoveParam instanceof Boolean);
 | 
			
		||||
        assertTrue((Boolean) convertedApproveMoveParam);
 | 
			
		||||
        final Serializable convertedRejectMoveParam = convertedParams.get(rejectMoveKey);
 | 
			
		||||
        assertTrue(convertedRejectMoveParam instanceof Boolean);
 | 
			
		||||
        assertTrue((Boolean) convertedRejectMoveParam);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSetPropertyConversion()
 | 
			
		||||
    {
 | 
			
		||||
        final String name = SetPropertyValueActionExecuter.NAME;
 | 
			
		||||
        final String propertyNameKey = SetPropertyValueActionExecuter.PARAM_PROPERTY;
 | 
			
		||||
        final String propertyValueKey = SetPropertyValueActionExecuter.PARAM_VALUE;
 | 
			
		||||
        final String propertyTypeKey = "prop_type";
 | 
			
		||||
        final String dummy_key_value = "dummy_key_value";
 | 
			
		||||
        final String propType = "d:text";
 | 
			
		||||
        final Map<String, Serializable> params =
 | 
			
		||||
                Map.of(propertyNameKey, IDENTIFIER_ASPECT, propertyValueKey, dummy_key_value, propertyTypeKey, propType);
 | 
			
		||||
 | 
			
		||||
        given(actionService.getActionDefinition(name)).willReturn(actionDefinition);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(propertyNameKey)).willReturn(actionDefinitionParam1);
 | 
			
		||||
        final QName qname = DataTypeDefinition.QNAME;
 | 
			
		||||
        given(actionDefinitionParam1.getType()).willReturn(qname);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(propertyValueKey)).willReturn(actionDefinitionParam2);
 | 
			
		||||
        final QName any = DataTypeDefinition.ANY;
 | 
			
		||||
        given(actionDefinitionParam2.getType()).willReturn(any);
 | 
			
		||||
        given(actionDefinition.getParameterDefintion(propertyTypeKey)).willReturn(null);
 | 
			
		||||
        given(actionDefinition.getAdhocPropertiesAllowed()).willReturn(true);
 | 
			
		||||
 | 
			
		||||
        given(dictionaryService.getDataType(qname)).willReturn(dataTypeDefinition1);
 | 
			
		||||
        given(dictionaryService.getDataType(any)).willReturn(dataTypeDefinition2);
 | 
			
		||||
        given(dataTypeDefinition2.getJavaClassName()).willReturn(Object.class.getName());
 | 
			
		||||
        given(namespaceService.getNamespaceURI(any())).willReturn(NamespaceService.DICTIONARY_MODEL_1_0_URI);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Map<String, Serializable> convertedParams = objectUnderTest.getConvertedParams(params, name);
 | 
			
		||||
 | 
			
		||||
        then(actionService).should().getActionDefinition(name);
 | 
			
		||||
        then(actionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(propertyNameKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(propertyValueKey);
 | 
			
		||||
        then(actionDefinition).should().getParameterDefintion(propertyTypeKey);
 | 
			
		||||
        then(actionDefinition).should().getAdhocPropertiesAllowed();
 | 
			
		||||
        then(actionDefinition).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(dictionaryService).should().getDataType(qname);
 | 
			
		||||
        then(dictionaryService).should(times(2)).getDataType(any);
 | 
			
		||||
        then(dictionaryService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(namespaceService).should().getNamespaceURI(any());
 | 
			
		||||
        then(namespaceService).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedPropNameParam = convertedParams.get(propertyNameKey);
 | 
			
		||||
        assertTrue(convertedPropNameParam instanceof QName);
 | 
			
		||||
        assertEquals(IDENTIFIER, ((QName) convertedPropNameParam).getLocalName());
 | 
			
		||||
        assertEquals(IDENTIFIER_ASPECT, ((QName) convertedPropNameParam).getPrefixString());
 | 
			
		||||
        assertEquals(NamespaceService.DICTIONARY_MODEL_1_0_URI, ((QName) convertedPropNameParam).getNamespaceURI());
 | 
			
		||||
 | 
			
		||||
        final Serializable convertedPropValParam = convertedParams.get(propertyValueKey);
 | 
			
		||||
        assertTrue(convertedPropValParam instanceof String);
 | 
			
		||||
        assertEquals(dummy_key_value, convertedPropValParam);
 | 
			
		||||
        final Serializable convertedPropTypeParam = convertedParams.get(propertyTypeKey);
 | 
			
		||||
        assertTrue(convertedPropTypeParam instanceof String);
 | 
			
		||||
        assertEquals(propType, convertedPropTypeParam);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testQnameServiceModelParamConversion() {
 | 
			
		||||
        given(namespaceService.getPrefixes(any())).willReturn(List.of("cm"));
 | 
			
		||||
        final String qname = "{cm-dummy-prefix}audio";
 | 
			
		||||
        final Serializable qnameParam = QName.createQName(qname);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Serializable convertedParam = objectUnderTest.convertParamFromServiceModel(qnameParam);
 | 
			
		||||
 | 
			
		||||
        then(namespaceService).should().getPrefixes(any());
 | 
			
		||||
        then(namespaceService).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertEquals("cm:audio", convertedParam);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testNodeRefServiceModelParamConversion() {
 | 
			
		||||
        //given
 | 
			
		||||
        final Serializable nodeRefParam = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_FOLDER_NODE_ID);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Serializable convertedParam = objectUnderTest.convertParamFromServiceModel(nodeRefParam);
 | 
			
		||||
 | 
			
		||||
        then(namespaceService).shouldHaveNoInteractions();
 | 
			
		||||
        assertEquals(DUMMY_FOLDER_NODE_ID, convertedParam);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testOtherServiceModelParamConversion() {
 | 
			
		||||
        //given
 | 
			
		||||
        final Serializable dummyStringParam = "dummy-param";
 | 
			
		||||
        //when
 | 
			
		||||
        final Serializable convertedParam = objectUnderTest.convertParamFromServiceModel(dummyStringParam);
 | 
			
		||||
 | 
			
		||||
        then(namespaceService).shouldHaveNoInteractions();
 | 
			
		||||
        assertEquals(dummyStringParam, convertedParam);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,117 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.service.cmr.rule.RuleType.INBOUND;
 | 
			
		||||
import static org.alfresco.service.cmr.rule.RuleType.OUTBOUND;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 | 
			
		||||
import static org.mockito.BDDMockito.then;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import junit.framework.TestCase;
 | 
			
		||||
import org.alfresco.repo.action.ActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.CompositeActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.RuntimeActionService;
 | 
			
		||||
import org.alfresco.repo.action.executer.CheckOutActionExecuter;
 | 
			
		||||
import org.alfresco.repo.action.executer.CopyActionExecuter;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.action.Action;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.StoreRef;
 | 
			
		||||
import org.alfresco.service.cmr.rule.Rule;
 | 
			
		||||
import org.assertj.core.api.Assertions;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.InjectMocks;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
@RunWith(MockitoJUnitRunner.class)
 | 
			
		||||
public class ActionPermissionValidatorTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    private static final String DUMMY_NODE_ID = "dummy-node-id";
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuntimeActionService runtimeActionService;
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private ActionPermissionValidator objectUnderTest;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testPositiveRulePermissionValidation()
 | 
			
		||||
    {
 | 
			
		||||
        //given
 | 
			
		||||
        final CompositeActionImpl compositeAction =
 | 
			
		||||
                new CompositeActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "composite-id");
 | 
			
		||||
        final Action action1 = new ActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "id-1",
 | 
			
		||||
                CopyActionExecuter.NAME);
 | 
			
		||||
        compositeAction.addAction(action1);
 | 
			
		||||
        final Action action2 = new ActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "id-2",
 | 
			
		||||
                CheckOutActionExecuter.NAME);
 | 
			
		||||
        compositeAction.addAction(action2);
 | 
			
		||||
        final Rule inputRule = new Rule();
 | 
			
		||||
        inputRule.setAction(compositeAction);
 | 
			
		||||
        inputRule.setRuleTypes(List.of(INBOUND));
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final Rule validatedRule = objectUnderTest.validateRulePermissions(inputRule);
 | 
			
		||||
 | 
			
		||||
        then(runtimeActionService).should().verifyActionAccessRestrictions(action1);
 | 
			
		||||
        then(runtimeActionService).should().verifyActionAccessRestrictions(action2);
 | 
			
		||||
        then(runtimeActionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
        ((CompositeActionImpl) validatedRule.getAction()).getActions()
 | 
			
		||||
                .forEach(action -> Assertions.assertThat(action.getParameterValue("actionContext")).isEqualTo("rule"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testNegativeRulePermissionValidation()
 | 
			
		||||
    {
 | 
			
		||||
        //given
 | 
			
		||||
        final CompositeActionImpl compositeAction =
 | 
			
		||||
                new CompositeActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "composite-id");
 | 
			
		||||
        final Action action1 = new ActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "id-1",
 | 
			
		||||
                CopyActionExecuter.NAME);
 | 
			
		||||
        compositeAction.addAction(action1);
 | 
			
		||||
        final Action action2 = new ActionImpl(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, DUMMY_NODE_ID), "id-2",
 | 
			
		||||
                CheckOutActionExecuter.NAME);
 | 
			
		||||
        compositeAction.addAction(action2);
 | 
			
		||||
        final Rule inputRule = new Rule();
 | 
			
		||||
        inputRule.setAction(compositeAction);
 | 
			
		||||
        inputRule.setRuleTypes(List.of(OUTBOUND));
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(() -> objectUnderTest.validateRulePermissions(inputRule));
 | 
			
		||||
 | 
			
		||||
        then(runtimeActionService).should().verifyActionAccessRestrictions(action1);
 | 
			
		||||
        then(runtimeActionService).should().verifyActionAccessRestrictions(action2);
 | 
			
		||||
        then(runtimeActionService).shouldHaveNoMoreInteractions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -39,18 +39,24 @@ import static org.mockito.ArgumentMatchers.any;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.BDDMockito.given;
 | 
			
		||||
import static org.mockito.BDDMockito.then;
 | 
			
		||||
import static org.mockito.Mockito.reset;
 | 
			
		||||
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.model.ContentModel;
 | 
			
		||||
import org.alfresco.rest.api.Nodes;
 | 
			
		||||
import org.alfresco.rest.api.model.Node;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundException;
 | 
			
		||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeService;
 | 
			
		||||
import org.alfresco.service.cmr.repository.StoreRef;
 | 
			
		||||
import org.alfresco.service.cmr.rule.RuleService;
 | 
			
		||||
import org.alfresco.service.cmr.security.PermissionService;
 | 
			
		||||
import org.junit.Assert;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.mockito.InjectMocks;
 | 
			
		||||
@@ -61,21 +67,33 @@ public class NodeValidatorTest
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    private static final String FOLDER_NODE_ID = "dummy-folder-node-id";
 | 
			
		||||
    private static final String LINK_TO_NODE_ID = "dummy-link-to-node-id";
 | 
			
		||||
    private static final String RULE_SET_ID = "dummy-rule-set-id";
 | 
			
		||||
    private static final String RULE_ID = "dummy-rule-id";
 | 
			
		||||
    private static final String PARENT_NODE_ID = "dummy-parent-node-id";
 | 
			
		||||
    private static final NodeRef folderNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_NODE_ID);
 | 
			
		||||
    private static final NodeRef ruleSetNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
 | 
			
		||||
    private static final NodeRef ruleNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
 | 
			
		||||
    private static final NodeRef parentNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, PARENT_NODE_ID);
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private Nodes nodesMock;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private Node ruleSetNodeMock;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private PermissionService permissionServiceMock;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleService ruleServiceMock;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private NodeService nodeServiceMock;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ChildAssociationRef primaryParentMock;
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private NodeValidator nodeValidator;
 | 
			
		||||
 | 
			
		||||
@@ -182,6 +200,20 @@ public class NodeValidatorTest
 | 
			
		||||
        assertThat(nodeRef).isNotNull().isEqualTo(ruleSetNodeRef);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testValidateRuleSetNodeNoParentId()
 | 
			
		||||
    {
 | 
			
		||||
        given(nodesMock.getNode(any())).willReturn(ruleSetNodeMock);
 | 
			
		||||
        given(nodeServiceMock.getPrimaryParent(any())).willReturn(primaryParentMock);
 | 
			
		||||
        given(primaryParentMock.getParentRef()).willReturn(parentNodeRef);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        final NodeRef nodeRef = nodeValidator.validateRuleSetNode(LINK_TO_NODE_ID,true);
 | 
			
		||||
 | 
			
		||||
        assertThat(nodeRef).isNotNull().isEqualTo(parentNodeRef);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void validateRuleSetNode_defaultId()
 | 
			
		||||
    {
 | 
			
		||||
@@ -329,6 +361,28 @@ public class NodeValidatorTest
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testIsRuleSetNode()
 | 
			
		||||
    {
 | 
			
		||||
        //resetting mock to bypass setup method
 | 
			
		||||
        resetNodesMock();
 | 
			
		||||
 | 
			
		||||
        boolean actual = nodeValidator.isRuleSetNode(RULE_SET_ID);
 | 
			
		||||
        Assert.assertTrue(actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testIsNotRuleSetNode()
 | 
			
		||||
    {
 | 
			
		||||
        //resetting mock to bypass setup method
 | 
			
		||||
        resetNodesMock();
 | 
			
		||||
 | 
			
		||||
        //using an id that doesn't belong to a ruleset node
 | 
			
		||||
        boolean actual = nodeValidator.isRuleSetNode(FOLDER_NODE_ID);
 | 
			
		||||
        Assert.assertFalse(actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testIsRuleSetNotNullAndShared()
 | 
			
		||||
    {
 | 
			
		||||
@@ -376,4 +430,12 @@ public class NodeValidatorTest
 | 
			
		||||
        then(ruleServiceMock).should().isRuleSetShared(ruleSetNodeRef);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void resetNodesMock() {
 | 
			
		||||
        reset(nodesMock);
 | 
			
		||||
        given(nodesMock.validateOrLookupNode(eq(FOLDER_NODE_ID), any())).willReturn(folderNodeRef);
 | 
			
		||||
        given(nodesMock.validateNode(RULE_SET_ID)).willReturn(ruleSetNodeRef);
 | 
			
		||||
        given(nodesMock.validateNode(RULE_ID)).willReturn(ruleNodeRef);
 | 
			
		||||
        given(nodesMock.nodeMatches(ruleSetNodeRef, Set.of(ContentModel.TYPE_SYSTEM_FOLDER), null)).willReturn(true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,121 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static java.util.Collections.emptyList;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.api.impl.rules.RuleLoader.IS_SHARED;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.RuleTrigger.OUTBOUND;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.RuleTrigger.UPDATE;
 | 
			
		||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.BDDMockito.given;
 | 
			
		||||
import static org.mockito.MockitoAnnotations.openMocks;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Rule;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.rule.RuleService;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.mockito.InjectMocks;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
 | 
			
		||||
/** Unit tests for {@link RuleLoader}. */
 | 
			
		||||
public class RuleLoaderTest
 | 
			
		||||
{
 | 
			
		||||
    private static final String NODE_ID = "node-id";
 | 
			
		||||
    private static final NodeRef NODE_REF = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, NODE_ID);
 | 
			
		||||
    private static final String TITLE = "title";
 | 
			
		||||
    private static final String DESCRIPTION = "description";
 | 
			
		||||
    private static final boolean ENABLED = true;
 | 
			
		||||
    private static final boolean CASCADE = true;
 | 
			
		||||
    private static final boolean EXECUTE_ASYNCHRONOUSLY = false;
 | 
			
		||||
    private static final List<String> TRIGGERS = List.of("update", "outbound");
 | 
			
		||||
    private static final NodeRef RULE_SET_NODE = new NodeRef("rule://set/");
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private RuleLoader ruleLoader;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleService ruleServiceMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private NodeValidator nodeValidatorMock;
 | 
			
		||||
    private org.alfresco.service.cmr.rule.Rule serviceRule = createServiceRule();
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    public void setUp()
 | 
			
		||||
    {
 | 
			
		||||
        openMocks(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLoadRule()
 | 
			
		||||
    {
 | 
			
		||||
        Rule rule = ruleLoader.loadRule(serviceRule, emptyList());
 | 
			
		||||
 | 
			
		||||
        Rule expected = Rule.builder().id(NODE_ID)
 | 
			
		||||
                            .name(TITLE)
 | 
			
		||||
                            .description(DESCRIPTION)
 | 
			
		||||
                            .enabled(ENABLED)
 | 
			
		||||
                            .cascade(CASCADE)
 | 
			
		||||
                            .asynchronous(EXECUTE_ASYNCHRONOUSLY)
 | 
			
		||||
                            .triggers(List.of(UPDATE, OUTBOUND)).create();
 | 
			
		||||
        assertThat(rule).isEqualTo(expected);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLoadRule_noExceptionWithNullInclude()
 | 
			
		||||
    {
 | 
			
		||||
        ruleLoader.loadRule(serviceRule, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLoadRule_includeIsShared()
 | 
			
		||||
    {
 | 
			
		||||
        // Simulate the rule set being shared.
 | 
			
		||||
        given(ruleServiceMock.getRuleSetNode(NODE_REF)).willReturn(RULE_SET_NODE);
 | 
			
		||||
        given(nodeValidatorMock.isRuleSetNotNullAndShared(RULE_SET_NODE)).willReturn(true);
 | 
			
		||||
 | 
			
		||||
        Rule rule = ruleLoader.loadRule(serviceRule, List.of(IS_SHARED));
 | 
			
		||||
 | 
			
		||||
        assertThat(rule).extracting("isShared").isEqualTo(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private org.alfresco.service.cmr.rule.Rule createServiceRule()
 | 
			
		||||
    {
 | 
			
		||||
        org.alfresco.service.cmr.rule.Rule rule = new org.alfresco.service.cmr.rule.Rule();
 | 
			
		||||
        rule.setNodeRef(NODE_REF);
 | 
			
		||||
        rule.setTitle(TITLE);
 | 
			
		||||
        rule.setDescription(DESCRIPTION);
 | 
			
		||||
        rule.setRuleDisabled(!ENABLED);
 | 
			
		||||
        rule.applyToChildren(CASCADE);
 | 
			
		||||
        rule.setExecuteAsynchronously(EXECUTE_ASYNCHRONOUSLY);
 | 
			
		||||
        rule.setRuleTypes(TRIGGERS);
 | 
			
		||||
        return rule;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -25,18 +25,22 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.INCLUSION_TYPE;
 | 
			
		||||
import static org.alfresco.rest.api.impl.rules.RuleSetLoader.OWNING_FOLDER;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.InclusionType.INHERITED;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.InclusionType.LINKED;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.InclusionType.OWNED;
 | 
			
		||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
 | 
			
		||||
import static org.mockito.BDDMockito.given;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import junit.framework.TestCase;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSet;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeService;
 | 
			
		||||
import org.alfresco.service.cmr.repository.StoreRef;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
@@ -51,8 +55,11 @@ public class RuleSetLoaderTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    private static final String FOLDER_ID = "dummy-folder-id";
 | 
			
		||||
    private static final String RULE_SET_ID = "dummy-rule-set-id";
 | 
			
		||||
    private static final NodeRef FOLDER_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_ID);
 | 
			
		||||
    private static final NodeRef RULE_SET_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
 | 
			
		||||
    private static final NodeRef FOLDER_NODE = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_ID);
 | 
			
		||||
    private static final NodeRef RULE_SET_NODE = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
 | 
			
		||||
    private static final String LINKING_FOLDER_ID = "linking-folder";
 | 
			
		||||
    private static final NodeRef LINKING_FOLDER = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, LINKING_FOLDER_ID);
 | 
			
		||||
    private static final NodeRef INHERITING_FOLDER = new NodeRef("inheriting://folder/");
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private RuleSetLoader ruleSetLoader;
 | 
			
		||||
@@ -60,6 +67,8 @@ public class RuleSetLoaderTest extends TestCase
 | 
			
		||||
    private NodeService nodeServiceMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ChildAssociationRef ruleSetAssociationMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ChildAssociationRef linkAssociationMock;
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -67,13 +76,16 @@ public class RuleSetLoaderTest extends TestCase
 | 
			
		||||
    {
 | 
			
		||||
        given(ruleSetAssociationMock.getParentRef()).willReturn(FOLDER_NODE);
 | 
			
		||||
        given(nodeServiceMock.getPrimaryParent(RULE_SET_NODE)).willReturn(ruleSetAssociationMock);
 | 
			
		||||
 | 
			
		||||
        given(linkAssociationMock.getParentRef()).willReturn(LINKING_FOLDER);
 | 
			
		||||
        given(nodeServiceMock.getParentAssocs(RULE_SET_NODE)).willReturn(List.of(ruleSetAssociationMock, linkAssociationMock));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLoadRuleSet_noIncludes()
 | 
			
		||||
    {
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, null);
 | 
			
		||||
        RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, null);
 | 
			
		||||
 | 
			
		||||
        RuleSet expected = RuleSet.builder().id(RULE_SET_ID).create();
 | 
			
		||||
        assertEquals(expected, actual);
 | 
			
		||||
@@ -83,9 +95,39 @@ public class RuleSetLoaderTest extends TestCase
 | 
			
		||||
    public void testLoadRuleSet_includeOwningFolder()
 | 
			
		||||
    {
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, List.of("owningFolder"));
 | 
			
		||||
        RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, List.of(OWNING_FOLDER));
 | 
			
		||||
 | 
			
		||||
        RuleSet expected = RuleSet.builder().id(RULE_SET_ID).owningFolder(FOLDER_NODE).create();
 | 
			
		||||
        assertEquals(expected, actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLoadRuleSet_includeInclusionType()
 | 
			
		||||
    {
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, List.of(INCLUSION_TYPE));
 | 
			
		||||
 | 
			
		||||
        RuleSet expected = RuleSet.builder().id(RULE_SET_ID).inclusionType(OWNED).create();
 | 
			
		||||
        assertEquals(expected, actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLoadRuleSet_linkedInclusionType()
 | 
			
		||||
    {
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, LINKING_FOLDER, List.of(INCLUSION_TYPE));
 | 
			
		||||
 | 
			
		||||
        RuleSet expected = RuleSet.builder().id(RULE_SET_ID).inclusionType(LINKED).create();
 | 
			
		||||
        assertEquals(expected, actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLoadRuleSet_inheritedInclusionType()
 | 
			
		||||
    {
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSet actual = ruleSetLoader.loadRuleSet(RULE_SET_NODE, INHERITING_FOLDER, List.of(INCLUSION_TYPE));
 | 
			
		||||
 | 
			
		||||
        RuleSet expected = RuleSet.builder().id(RULE_SET_ID).inclusionType(INHERITED).create();
 | 
			
		||||
        assertEquals(expected, actual);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,8 @@ package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static java.util.Collections.emptyList;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.any;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.anyBoolean;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.BDDMockito.given;
 | 
			
		||||
@@ -36,7 +38,10 @@ import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import junit.framework.TestCase;
 | 
			
		||||
import org.alfresco.repo.rule.RuleModel;
 | 
			
		||||
import org.alfresco.repo.rule.RuntimeRuleService;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSet;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
@@ -59,8 +64,10 @@ import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
public class RuleSetsImplTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    private static final String FOLDER_ID = "dummy-folder-id";
 | 
			
		||||
    private static final String LINK_TO_NODE_ID = "dummy-link-to-node-id";
 | 
			
		||||
    private static final String RULE_SET_ID = "dummy-rule-set-id";
 | 
			
		||||
    private static final NodeRef FOLDER_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_ID);
 | 
			
		||||
    private static final NodeRef LINK_TO_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, LINK_TO_NODE_ID);
 | 
			
		||||
    private static final NodeRef RULE_SET_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
 | 
			
		||||
    private static final Paging PAGING = Paging.DEFAULT;
 | 
			
		||||
    private static final List<String> INCLUDES = List.of("dummy-includes");
 | 
			
		||||
@@ -72,9 +79,15 @@ public class RuleSetsImplTest extends TestCase
 | 
			
		||||
    @Mock
 | 
			
		||||
    private NodeValidator nodeValidatorMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private NodeService nodeServiceMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleService ruleServiceMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuntimeRuleService runtimeRuleServiceMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleSet ruleSetMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ChildAssociationRef assocRef;
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -82,12 +95,13 @@ public class RuleSetsImplTest extends TestCase
 | 
			
		||||
    {
 | 
			
		||||
        MockitoAnnotations.openMocks(this);
 | 
			
		||||
 | 
			
		||||
        given(nodeValidatorMock.validateFolderNode(eq(LINK_TO_NODE_ID), anyBoolean())).willReturn(LINK_TO_NODE);
 | 
			
		||||
        given(nodeValidatorMock.validateRuleSetNode(LINK_TO_NODE_ID,true)).willReturn(LINK_TO_NODE);
 | 
			
		||||
        given(nodeValidatorMock.validateFolderNode(eq(FOLDER_ID), anyBoolean())).willReturn(FOLDER_NODE);
 | 
			
		||||
        //given(nodeValidatorMock.validateFolderNode(eq(RULE_SET_ID), anyBoolean())).willReturn(RULE_SET_NODE);
 | 
			
		||||
        given(nodeValidatorMock.validateRuleSetNode(RULE_SET_ID, FOLDER_NODE)).willReturn(RULE_SET_NODE);
 | 
			
		||||
 | 
			
		||||
        given(ruleServiceMock.getRuleSetNode(FOLDER_NODE)).willReturn(RULE_SET_NODE);
 | 
			
		||||
        given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, INCLUDES)).willReturn(ruleSetMock);
 | 
			
		||||
        given(ruleSetLoaderMock.loadRuleSet(RULE_SET_NODE, FOLDER_NODE, INCLUDES)).willReturn(ruleSetMock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -138,4 +152,85 @@ public class RuleSetsImplTest extends TestCase
 | 
			
		||||
 | 
			
		||||
        assertEquals(ruleSetMock, actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLinkToFolderRuleSet()
 | 
			
		||||
    {
 | 
			
		||||
        NodeRef childNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "dummy-child-id");
 | 
			
		||||
 | 
			
		||||
        given(ruleServiceMock.hasRules(any(NodeRef.class))).willReturn(true, false);
 | 
			
		||||
        given(runtimeRuleServiceMock.getSavedRuleFolderAssoc(any(NodeRef.class))).willReturn(assocRef);
 | 
			
		||||
        given(assocRef.getChildRef()).willReturn(childNodeRef);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        String actual = ruleSets.linkToRuleSet(FOLDER_ID,LINK_TO_NODE_ID).getId();
 | 
			
		||||
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(FOLDER_NODE);
 | 
			
		||||
        then(runtimeRuleServiceMock).should().getSavedRuleFolderAssoc(LINK_TO_NODE);
 | 
			
		||||
        then(runtimeRuleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(nodeServiceMock).should().addChild(FOLDER_NODE, childNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
 | 
			
		||||
        then(nodeServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
        assertEquals(childNodeRef.getId(),actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLinkToRuleSet()
 | 
			
		||||
    {
 | 
			
		||||
        NodeRef childNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "dummy-child-id");
 | 
			
		||||
 | 
			
		||||
        given(nodeValidatorMock.isRuleSetNode(any())).willReturn(true);
 | 
			
		||||
        given(ruleServiceMock.hasRules(any(NodeRef.class))).willReturn(true, false);
 | 
			
		||||
        given(runtimeRuleServiceMock.getSavedRuleFolderAssoc(any(NodeRef.class))).willReturn(assocRef);
 | 
			
		||||
        given(assocRef.getChildRef()).willReturn(childNodeRef);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        String actual = ruleSets.linkToRuleSet(FOLDER_ID,LINK_TO_NODE_ID).getId();
 | 
			
		||||
 | 
			
		||||
        then(nodeValidatorMock).should().validateFolderNode(FOLDER_ID,true);
 | 
			
		||||
        then(nodeValidatorMock).should().isRuleSetNode(LINK_TO_NODE_ID);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(LINK_TO_NODE_ID,true);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(FOLDER_NODE);
 | 
			
		||||
        then(runtimeRuleServiceMock).should().getSavedRuleFolderAssoc(LINK_TO_NODE);
 | 
			
		||||
        then(runtimeRuleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(nodeServiceMock).should().addChild(FOLDER_NODE, childNodeRef, RuleModel.ASSOC_RULE_FOLDER, RuleModel.ASSOC_RULE_FOLDER);
 | 
			
		||||
        then(nodeServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
        assertEquals(childNodeRef.getId(),actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLinkToRuleSet_targetFolderHasNoRules()
 | 
			
		||||
    {
 | 
			
		||||
        given(ruleServiceMock.hasRules(LINK_TO_NODE)).willReturn(false);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
 | 
			
		||||
                () -> ruleSets.linkToRuleSet(FOLDER_ID, LINK_TO_NODE_ID)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        then(nodeServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(runtimeRuleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testLinkToRuleSet_folderShouldntHavePreExistingRules()
 | 
			
		||||
    {
 | 
			
		||||
        given(ruleServiceMock.hasRules(any(NodeRef.class))).willReturn(true, true);
 | 
			
		||||
 | 
			
		||||
        //when
 | 
			
		||||
        assertThatExceptionOfType(InvalidArgumentException.class).isThrownBy(
 | 
			
		||||
                () -> ruleSets.linkToRuleSet(FOLDER_ID, LINK_TO_NODE_ID));
 | 
			
		||||
 | 
			
		||||
        then(nodeServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(LINK_TO_NODE);
 | 
			
		||||
        then(ruleServiceMock).should().hasRules(FOLDER_NODE);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(runtimeRuleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,145 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.rest.api.impl.rules;
 | 
			
		||||
 | 
			
		||||
import static java.util.Collections.emptyMap;
 | 
			
		||||
 | 
			
		||||
import static org.alfresco.repo.rule.RuleModel.ASPECT_IGNORE_INHERITED_RULES;
 | 
			
		||||
import static org.alfresco.rest.api.model.rules.RuleSetting.IS_INHERITANCE_ENABLED_KEY;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.anyBoolean;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.BDDMockito.given;
 | 
			
		||||
import static org.mockito.BDDMockito.then;
 | 
			
		||||
 | 
			
		||||
import junit.framework.TestCase;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSetting;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.NotFoundException;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeService;
 | 
			
		||||
import org.alfresco.service.cmr.repository.StoreRef;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.InjectMocks;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
/** Unit tests for {@link RuleSettingsImpl}. */
 | 
			
		||||
@Experimental
 | 
			
		||||
@RunWith (MockitoJUnitRunner.class)
 | 
			
		||||
public class RuleSettingsImplTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    private static final String FOLDER_ID = "dummy-folder-id";
 | 
			
		||||
    private static final NodeRef FOLDER_NODE = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_ID);
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private RuleSettingsImpl ruleSettings;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private NodeValidator nodeValidatorMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private NodeService nodeServiceMock;
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setUp()
 | 
			
		||||
    {
 | 
			
		||||
        given(nodeValidatorMock.validateFolderNode(eq(FOLDER_ID), anyBoolean())).willReturn(FOLDER_NODE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetRuleSetting_disabled()
 | 
			
		||||
    {
 | 
			
		||||
        given(nodeServiceMock.hasAspect(FOLDER_NODE, ASPECT_IGNORE_INHERITED_RULES)).willReturn(true);
 | 
			
		||||
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSetting ruleSetting = ruleSettings.getRuleSetting(FOLDER_ID, IS_INHERITANCE_ENABLED_KEY);
 | 
			
		||||
 | 
			
		||||
        RuleSetting expected = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(false).create();
 | 
			
		||||
        assertEquals(expected, ruleSetting);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetRuleSetting_enabled()
 | 
			
		||||
    {
 | 
			
		||||
        given(nodeServiceMock.hasAspect(FOLDER_NODE, ASPECT_IGNORE_INHERITED_RULES)).willReturn(false);
 | 
			
		||||
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSetting ruleSetting = ruleSettings.getRuleSetting(FOLDER_ID, IS_INHERITANCE_ENABLED_KEY);
 | 
			
		||||
 | 
			
		||||
        RuleSetting expected = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(true).create();
 | 
			
		||||
        assertEquals(expected, ruleSetting);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetRuleSetting_unrecognisedKey()
 | 
			
		||||
    {
 | 
			
		||||
        assertThatExceptionOfType(NotFoundException.class)
 | 
			
		||||
                .isThrownBy(() -> ruleSettings.getRuleSetting(FOLDER_ID, "-fakeSetting-"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSetRuleSetting_enable()
 | 
			
		||||
    {
 | 
			
		||||
        RuleSetting ruleSetting = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(true).create();
 | 
			
		||||
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSetting actual = ruleSettings.setRuleSetting(FOLDER_ID, ruleSetting);
 | 
			
		||||
 | 
			
		||||
        assertEquals(ruleSetting, actual);
 | 
			
		||||
        then(nodeServiceMock).should().removeAspect(FOLDER_NODE, ASPECT_IGNORE_INHERITED_RULES);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSetRuleSetting_disable()
 | 
			
		||||
    {
 | 
			
		||||
        RuleSetting ruleSetting = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(false).create();
 | 
			
		||||
 | 
			
		||||
        // Call the method under test.
 | 
			
		||||
        RuleSetting actual = ruleSettings.setRuleSetting(FOLDER_ID, ruleSetting);
 | 
			
		||||
 | 
			
		||||
        assertEquals(ruleSetting, actual);
 | 
			
		||||
        then(nodeServiceMock).should().addAspect(FOLDER_NODE, ASPECT_IGNORE_INHERITED_RULES, emptyMap());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSetRuleSetting_unrecognisedKey()
 | 
			
		||||
    {
 | 
			
		||||
        RuleSetting ruleSetting = RuleSetting.builder().key("-fakeSetting-").value(true).create();
 | 
			
		||||
        assertThatExceptionOfType(NotFoundException.class)
 | 
			
		||||
                .isThrownBy(() -> ruleSettings.setRuleSetting(FOLDER_ID, ruleSetting));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSetRuleSetting_nonBooleanValue()
 | 
			
		||||
    {
 | 
			
		||||
        RuleSetting ruleSetting = RuleSetting.builder().key(IS_INHERITANCE_ENABLED_KEY).value(123456).create();
 | 
			
		||||
 | 
			
		||||
        assertThatExceptionOfType(IllegalArgumentException.class)
 | 
			
		||||
                .isThrownBy(() -> ruleSettings.setRuleSetting(FOLDER_ID, ruleSetting));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -38,14 +38,17 @@ import static org.mockito.BDDMockito.then;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
import static org.mockito.Mockito.times;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.stream.IntStream;
 | 
			
		||||
 | 
			
		||||
import junit.framework.TestCase;
 | 
			
		||||
import org.alfresco.repo.action.ActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.CompositeActionImpl;
 | 
			
		||||
import org.alfresco.rest.api.Nodes;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.CompositeCondition;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.Rule;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
 | 
			
		||||
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
 | 
			
		||||
@@ -54,7 +57,7 @@ import org.alfresco.rest.framework.core.exceptions.RelationshipResourceNotFoundE
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.action.Action;
 | 
			
		||||
import org.alfresco.service.cmr.action.CompositeAction;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.StoreRef;
 | 
			
		||||
import org.alfresco.service.cmr.rule.RuleService;
 | 
			
		||||
@@ -64,7 +67,6 @@ import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.InjectMocks;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.Mockito;
 | 
			
		||||
import org.mockito.MockitoAnnotations;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
@@ -74,20 +76,32 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
    private static final String FOLDER_NODE_ID = "dummy-folder-node-id";
 | 
			
		||||
    private static final String RULE_SET_ID = "dummy-rule-set-id";
 | 
			
		||||
    private static final String RULE_ID = "dummy-rule-id";
 | 
			
		||||
    private static final NodeRef folderNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_NODE_ID);
 | 
			
		||||
    private static final NodeRef ruleSetNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
 | 
			
		||||
    private static final NodeRef ruleNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
 | 
			
		||||
    private static final Paging paging = Paging.DEFAULT;
 | 
			
		||||
    private static final Action action = new ActionImpl(folderNodeRef, "actionId", "actionDefinitionName");
 | 
			
		||||
    private static final NodeRef FOLDER_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, FOLDER_NODE_ID);
 | 
			
		||||
    private static final NodeRef RULE_SET_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_SET_ID);
 | 
			
		||||
    private static final NodeRef RULE_NODE_REF = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
 | 
			
		||||
    private static final Paging PAGING = Paging.DEFAULT;
 | 
			
		||||
    private static final List<String> INCLUDE = emptyList();
 | 
			
		||||
    private static final String ACTION_DEFINITION_NAME = "actionDefinitionName";
 | 
			
		||||
    private static final Map<String, Serializable> DUMMY_PARAMS = Map.of("dummy-key", "dummy-value");
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private Nodes nodesMock;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private NodeValidator nodeValidatorMock;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleService ruleServiceMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleLoader ruleLoaderMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ActionParameterConverter actionParameterConverterMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private ActionPermissionValidator actionPermissionValidatorMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private org.alfresco.service.cmr.rule.Rule serviceRuleMock;
 | 
			
		||||
    @Mock
 | 
			
		||||
    private Rule ruleMock;
 | 
			
		||||
    private org.alfresco.service.cmr.rule.Rule ruleModel = createRule(RULE_ID);
 | 
			
		||||
    private CompositeAction compositeAction = new CompositeActionImpl(RULE_NODE_REF, "compositeActionId");
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private RulesImpl rules;
 | 
			
		||||
@@ -96,36 +110,39 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setUp() throws Exception
 | 
			
		||||
    {
 | 
			
		||||
        MockitoAnnotations.openMocks(this);
 | 
			
		||||
        given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
        given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(ruleSetNodeRef);
 | 
			
		||||
        given(nodeValidatorMock.validateRuleNode(any(), any())).willReturn(ruleNodeRef);
 | 
			
		||||
        given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
        given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
 | 
			
		||||
        given(nodeValidatorMock.validateRuleNode(any(), any())).willReturn(RULE_NODE_REF);
 | 
			
		||||
 | 
			
		||||
        given(ruleServiceMock.getRule(RULE_NODE_REF)).willReturn(ruleModel);
 | 
			
		||||
        given(ruleServiceMock.getRules(FOLDER_NODE_REF)).willReturn(List.of(ruleModel));
 | 
			
		||||
 | 
			
		||||
        given(ruleLoaderMock.loadRule(ruleModel, INCLUDE)).willReturn(ruleMock);
 | 
			
		||||
 | 
			
		||||
        compositeAction.addAction(new ActionImpl(FOLDER_NODE_REF, "actionId", ACTION_DEFINITION_NAME, DUMMY_PARAMS));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetRules()
 | 
			
		||||
    {
 | 
			
		||||
        given(ruleServiceMock.getRules(any())).willReturn(List.of(createRule(RULE_ID)));
 | 
			
		||||
 | 
			
		||||
        given(ruleLoaderMock.loadRule(ruleModel, emptyList())).willReturn(ruleMock);
 | 
			
		||||
        // when
 | 
			
		||||
        final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging);
 | 
			
		||||
        final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
 | 
			
		||||
 | 
			
		||||
        then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().isRuleSetNotNullAndShared(ruleSetNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().getRules(folderNodeRef);
 | 
			
		||||
        then(ruleServiceMock).should().getRules(FOLDER_NODE_REF);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleLoaderMock).should().loadRule(ruleModel, emptyList());
 | 
			
		||||
        then(ruleLoaderMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(rulesPage)
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
            .extracting(CollectionWithPagingInfo::getCollection)
 | 
			
		||||
                .extracting(CollectionWithPagingInfo::getCollection)
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
            .extracting(Collection::size)
 | 
			
		||||
                .extracting(Collection::size)
 | 
			
		||||
                .isEqualTo(1);
 | 
			
		||||
        assertThat(rulesPage.getCollection().stream().findFirst().orElse(null))
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
            .extracting(Rule::getId)
 | 
			
		||||
                .isEqualTo(RULE_ID);
 | 
			
		||||
        assertThat(rulesPage.getCollection().stream().findFirst().get()).isEqualTo(ruleMock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -134,16 +151,16 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        given(ruleServiceMock.getRules(any())).willReturn(emptyList());
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging);
 | 
			
		||||
        final CollectionWithPagingInfo<Rule> rulesPage = rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
 | 
			
		||||
 | 
			
		||||
        then(ruleServiceMock).should().getRules(folderNodeRef);
 | 
			
		||||
        then(ruleServiceMock).should().getRules(FOLDER_NODE_REF);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(rulesPage)
 | 
			
		||||
            .isNotNull()
 | 
			
		||||
            .extracting(CollectionWithPagingInfo::getCollection)
 | 
			
		||||
            .isNotNull()
 | 
			
		||||
            .extracting(Collection::isEmpty)
 | 
			
		||||
            .isEqualTo(true);
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
                .extracting(CollectionWithPagingInfo::getCollection)
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
                .extracting(Collection::isEmpty)
 | 
			
		||||
                .isEqualTo(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -156,7 +173,7 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging));
 | 
			
		||||
                    () -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
@@ -170,15 +187,15 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        for (Exception exception : ruleSetValidationExceptions())
 | 
			
		||||
        {
 | 
			
		||||
            Mockito.reset(nodeValidatorMock);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, paging));
 | 
			
		||||
                    () -> rules.getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
            then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        }
 | 
			
		||||
@@ -187,23 +204,17 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testGetRuleById()
 | 
			
		||||
    {
 | 
			
		||||
        given(ruleServiceMock.getRule(any())).willReturn(createRule(RULE_ID));
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        final Rule rule = rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
 | 
			
		||||
        final Rule rule = rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE);
 | 
			
		||||
 | 
			
		||||
        then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleNode(RULE_ID, ruleSetNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().isRuleSetNotNullAndShared(ruleSetNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(nodesMock).shouldHaveNoInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().getRule(ruleNodeRef);
 | 
			
		||||
        then(ruleServiceMock).should().getRule(RULE_NODE_REF);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(rule)
 | 
			
		||||
                .isNotNull()
 | 
			
		||||
            .extracting(Rule::getId)
 | 
			
		||||
                .isEqualTo(RULE_ID);
 | 
			
		||||
        assertThat(rule).isEqualTo(ruleMock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -216,7 +227,7 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
                    () -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
@@ -230,15 +241,15 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        for (Exception exception : ruleSetValidationExceptions())
 | 
			
		||||
        {
 | 
			
		||||
            Mockito.reset(nodeValidatorMock);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
                    () -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
            then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        }
 | 
			
		||||
@@ -250,71 +261,76 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        for (Exception exception : ruleValidationExceptions())
 | 
			
		||||
        {
 | 
			
		||||
            Mockito.reset(nodeValidatorMock);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(ruleSetNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleNode(any(), any())).willThrow(exception);
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
                    () -> rules.getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, false);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleNode(RULE_ID, ruleSetNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
            then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Create a single rule. */
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a single rule.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreateRules()
 | 
			
		||||
    {
 | 
			
		||||
        Rule ruleBody = mock(Rule.class);
 | 
			
		||||
        List<Rule> ruleList = List.of(ruleBody);
 | 
			
		||||
        org.alfresco.service.cmr.rule.Rule serviceRuleBody = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
        given(ruleBody.toServiceModel(nodesMock)).willReturn(serviceRuleBody);
 | 
			
		||||
        org.alfresco.service.cmr.rule.Rule serviceRule = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
        given(ruleServiceMock.saveRule(folderNodeRef, serviceRuleBody)).willReturn(serviceRule);
 | 
			
		||||
        given(serviceRule.getNodeRef()).willReturn(ruleNodeRef);
 | 
			
		||||
        given(serviceRule.getAction()).willReturn(action);
 | 
			
		||||
        List<Rule> ruleList = List.of(ruleMock);
 | 
			
		||||
        given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
 | 
			
		||||
        given(serviceRuleMock.getAction()).willReturn(compositeAction);
 | 
			
		||||
        given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(arg -> arg.getArguments()[1]);
 | 
			
		||||
        given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
 | 
			
		||||
        given(actionPermissionValidatorMock.validateRulePermissions(any())).willAnswer(arg -> arg.getArguments()[0]);
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        List<Rule> actual = rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), ruleList);
 | 
			
		||||
        List<Rule> actual = rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), ruleList, INCLUDE);
 | 
			
		||||
 | 
			
		||||
        then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(nodeValidatorMock).should().isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef);
 | 
			
		||||
        then(ruleServiceMock).should().saveRule(folderNodeRef, ruleBody.toServiceModel(nodesMock));
 | 
			
		||||
        then(actionParameterConverterMock).should().getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
 | 
			
		||||
        then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
 | 
			
		||||
        then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock));
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        List<Rule> expected = List.of(Rule.from(serviceRule, false));
 | 
			
		||||
        List<Rule> expected = List.of(ruleMock);
 | 
			
		||||
        assertThat(actual).isEqualTo(expected);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check that when passing the default rule set then we don't perform any validation around the rule set node. */
 | 
			
		||||
    /**
 | 
			
		||||
     * Check that when passing the default rule set then we don't perform any validation around the rule set node.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreateRules_defaultRuleSet()
 | 
			
		||||
    {
 | 
			
		||||
        Rule ruleBody = mock(Rule.class);
 | 
			
		||||
        List<Rule> ruleList = List.of(ruleBody);
 | 
			
		||||
        org.alfresco.service.cmr.rule.Rule serviceRuleBody = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
        given(ruleBody.toServiceModel(nodesMock)).willReturn(serviceRuleBody);
 | 
			
		||||
        org.alfresco.service.cmr.rule.Rule serviceRule = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
        given(ruleServiceMock.saveRule(folderNodeRef, serviceRuleBody)).willReturn(serviceRule);
 | 
			
		||||
        given(serviceRule.getNodeRef()).willReturn(ruleNodeRef);
 | 
			
		||||
        given(serviceRule.getAction()).willReturn(action);
 | 
			
		||||
        List<Rule> ruleList = List.of(ruleMock);
 | 
			
		||||
        given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
 | 
			
		||||
        given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(arg -> arg.getArguments()[1]);
 | 
			
		||||
        given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
 | 
			
		||||
        given(serviceRuleMock.getAction()).willReturn(compositeAction);
 | 
			
		||||
        given(actionPermissionValidatorMock.validateRulePermissions(any())).willAnswer(arg -> arg.getArguments()[0]);
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        List<Rule> actual = rules.createRules(folderNodeRef.getId(), DEFAULT_ID, ruleList);
 | 
			
		||||
        List<Rule> actual = rules.createRules(FOLDER_NODE_REF.getId(), DEFAULT_ID, ruleList, INCLUDE);
 | 
			
		||||
 | 
			
		||||
        then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
        then(nodeValidatorMock).should().isRuleSetNotNullAndShared(null, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().saveRule(folderNodeRef, ruleBody.toServiceModel(nodesMock));
 | 
			
		||||
        then(actionParameterConverterMock).should().getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
 | 
			
		||||
        then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
 | 
			
		||||
        then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleMock.toServiceModel(nodesMock));
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        List<Rule> expected = List.of(Rule.from(serviceRule, false));
 | 
			
		||||
        List<Rule> expected = List.of(ruleMock);
 | 
			
		||||
        assertThat(actual).isEqualTo(expected);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -324,43 +340,49 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        List<Rule> ruleList = emptyList();
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        List<Rule> actual = rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), ruleList);
 | 
			
		||||
        List<Rule> actual = rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), ruleList, INCLUDE);
 | 
			
		||||
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        assertThat(actual).isEqualTo(emptyList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Create three rules in a single call and check they are all passed to the RuleService. */
 | 
			
		||||
    /**
 | 
			
		||||
     * Create three rules in a single call and check they are all passed to the RuleService.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreateRules_createMultipleRules()
 | 
			
		||||
    {
 | 
			
		||||
        List<Rule> ruleBodyList = new ArrayList<>();
 | 
			
		||||
        List<Rule> expected = new ArrayList<>();
 | 
			
		||||
        for (String ruleId : List.of("A", "B", "C"))
 | 
			
		||||
        {
 | 
			
		||||
            Rule ruleBody = mock(Rule.class);
 | 
			
		||||
            ruleBodyList.add(ruleBody);
 | 
			
		||||
            org.alfresco.service.cmr.rule.Rule serviceRuleBody = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
            given(ruleBody.toServiceModel(nodesMock)).willReturn(serviceRuleBody);
 | 
			
		||||
            org.alfresco.service.cmr.rule.Rule serviceRule = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
            given(ruleServiceMock.saveRule(folderNodeRef, serviceRuleBody)).willReturn(serviceRule);
 | 
			
		||||
            NodeRef ruleNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, ruleId);
 | 
			
		||||
            given(serviceRule.getNodeRef()).willReturn(ruleNodeRef);
 | 
			
		||||
            given(serviceRule.getAction()).willReturn(action);
 | 
			
		||||
            expected.add(Rule.from(serviceRule, false));
 | 
			
		||||
        }
 | 
			
		||||
        IntStream.range(0, 3).forEach(i -> {
 | 
			
		||||
            Rule ruleBodyMock = mock(Rule.class);
 | 
			
		||||
            ruleBodyList.add(ruleBodyMock);
 | 
			
		||||
            org.alfresco.service.cmr.rule.Rule serviceRuleMockInner = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
            given(ruleBodyMock.toServiceModel(nodesMock)).willReturn(serviceRuleMockInner);
 | 
			
		||||
            final CompositeAction compositeActionInner = new CompositeActionImpl(RULE_NODE_REF, "compositeActionInnerId");
 | 
			
		||||
            compositeActionInner.addAction(new ActionImpl(FOLDER_NODE_REF, "actionInnerId", ACTION_DEFINITION_NAME, DUMMY_PARAMS));
 | 
			
		||||
            given(serviceRuleMockInner.getAction()).willReturn(compositeActionInner);
 | 
			
		||||
            given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMockInner)).willAnswer(arg -> arg.getArguments()[1]);
 | 
			
		||||
            Rule ruleMockInner = mock(Rule.class);
 | 
			
		||||
            given(ruleLoaderMock.loadRule(serviceRuleMockInner, INCLUDE)).willReturn(ruleMockInner);
 | 
			
		||||
            expected.add(ruleMockInner);
 | 
			
		||||
            given(actionPermissionValidatorMock.validateRulePermissions(any())).willAnswer(arg -> arg.getArguments()[0]);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        List<Rule> actual = rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), ruleBodyList);
 | 
			
		||||
        List<Rule> actual = rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), ruleBodyList, INCLUDE);
 | 
			
		||||
 | 
			
		||||
        then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should(times(ruleBodyList.size())).isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        for (Rule ruleBody : ruleBodyList)
 | 
			
		||||
        {
 | 
			
		||||
            then(ruleServiceMock).should().saveRule(folderNodeRef, ruleBody.toServiceModel(nodesMock));
 | 
			
		||||
            then(actionPermissionValidatorMock).should().validateRulePermissions(ruleBody.toServiceModel(nodesMock));
 | 
			
		||||
            then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, ruleBody.toServiceModel(nodesMock));
 | 
			
		||||
        }
 | 
			
		||||
        then(actionParameterConverterMock).should(times(3)).getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
 | 
			
		||||
        then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(actual).isEqualTo(expected);
 | 
			
		||||
    }
 | 
			
		||||
@@ -375,7 +397,7 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), emptyList()));
 | 
			
		||||
                    () -> rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), emptyList(), INCLUDE));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
@@ -389,52 +411,46 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        for (Exception exception : ruleSetValidationExceptions())
 | 
			
		||||
        {
 | 
			
		||||
            Mockito.reset(nodeValidatorMock);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.createRules(folderNodeRef.getId(), ruleSetNodeRef.getId(), emptyList()));
 | 
			
		||||
                    () -> rules.createRules(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), emptyList(), INCLUDE));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
            then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Check that we can update a rule. */
 | 
			
		||||
    /**
 | 
			
		||||
     * Check that we can update a rule.
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpdateRuleById()
 | 
			
		||||
    {
 | 
			
		||||
        Rule ruleBody = mock(Rule.class);
 | 
			
		||||
        given(nodeValidatorMock.isRuleSetNotNullAndShared(any(), any())).willReturn(true);
 | 
			
		||||
        org.alfresco.service.cmr.rule.Rule serviceRuleBody = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
        given(ruleBody.toServiceModel(nodesMock)).willReturn(serviceRuleBody);
 | 
			
		||||
        org.alfresco.service.cmr.rule.Rule serviceRule = mock(org.alfresco.service.cmr.rule.Rule.class);
 | 
			
		||||
        given(ruleServiceMock.saveRule(folderNodeRef, serviceRuleBody)).willReturn(serviceRule);
 | 
			
		||||
        given(serviceRule.getNodeRef()).willReturn(ruleNodeRef);
 | 
			
		||||
        given(serviceRule.getAction()).willReturn(action);
 | 
			
		||||
        given(ruleMock.toServiceModel(nodesMock)).willReturn(serviceRuleMock);
 | 
			
		||||
        given(ruleServiceMock.saveRule(FOLDER_NODE_REF, serviceRuleMock)).willAnswer(a -> a.getArguments()[1]);
 | 
			
		||||
        given(serviceRuleMock.getAction()).willReturn(compositeAction);
 | 
			
		||||
        given(ruleLoaderMock.loadRule(serviceRuleMock, INCLUDE)).willReturn(ruleMock);
 | 
			
		||||
        given(actionPermissionValidatorMock.validateRulePermissions(any())).willAnswer(arg -> arg.getArguments()[0]);
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        Rule updatedRule = rules.updateRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID, ruleBody);
 | 
			
		||||
        Rule updatedRule = rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, ruleMock, INCLUDE);
 | 
			
		||||
 | 
			
		||||
        then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleNode(RULE_ID, ruleSetNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().isRuleSetNotNullAndShared(ruleSetNodeRef, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().saveRule(folderNodeRef, serviceRuleBody);
 | 
			
		||||
        then(ruleServiceMock).should().saveRule(FOLDER_NODE_REF, serviceRuleMock);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Rule expected = Rule.builder().id(RULE_ID)
 | 
			
		||||
                                      .enabled(true)
 | 
			
		||||
                                      .shared(true)
 | 
			
		||||
                                      .triggers(emptyList())
 | 
			
		||||
                                      .conditions(CompositeCondition.builder().inverted(false).create())
 | 
			
		||||
                                      .create();
 | 
			
		||||
        assertThat(updatedRule).isEqualTo(expected);
 | 
			
		||||
        then(actionParameterConverterMock).should().getConvertedParams(DUMMY_PARAMS, ACTION_DEFINITION_NAME);
 | 
			
		||||
        then(actionParameterConverterMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(actionPermissionValidatorMock).should().validateRulePermissions(serviceRuleMock);
 | 
			
		||||
        then(actionPermissionValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(updatedRule).isEqualTo(ruleMock);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -447,7 +463,7 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.updateRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID, mock(Rule.class)));
 | 
			
		||||
                    () -> rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, mock(Rule.class), INCLUDE));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
@@ -461,15 +477,15 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        for (Exception exception : ruleSetValidationExceptions())
 | 
			
		||||
        {
 | 
			
		||||
            Mockito.reset(nodeValidatorMock);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.updateRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID, mock(Rule.class)));
 | 
			
		||||
                    () -> rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, mock(Rule.class), INCLUDE));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
            then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        }
 | 
			
		||||
@@ -481,37 +497,35 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        for (Exception exception : ruleValidationExceptions())
 | 
			
		||||
        {
 | 
			
		||||
            Mockito.reset(nodeValidatorMock);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(ruleSetNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleNode(any(), any())).willThrow(exception);
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.updateRuleById(folderNodeRef.getId(), ruleSetNodeRef.getId(), RULE_ID, mock(Rule.class)));
 | 
			
		||||
                    () -> rules.updateRuleById(FOLDER_NODE_REF.getId(), RULE_SET_NODE_REF.getId(), RULE_ID, mock(Rule.class), INCLUDE));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleNode(RULE_ID, ruleSetNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
            then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDeleteRuleById() {
 | 
			
		||||
        org.alfresco.service.cmr.rule.Rule rule = createRule(RULE_ID);
 | 
			
		||||
        given(ruleServiceMock.getRule(any())).willReturn(rule);
 | 
			
		||||
 | 
			
		||||
    public void testDeleteRuleById()
 | 
			
		||||
    {
 | 
			
		||||
        //when
 | 
			
		||||
        rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
 | 
			
		||||
 | 
			
		||||
        then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleNode(RULE_ID, ruleSetNodeRef);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
 | 
			
		||||
        then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        then(nodesMock).shouldHaveNoInteractions();
 | 
			
		||||
        then(ruleServiceMock).should().getRule(ruleNodeRef);
 | 
			
		||||
        then(ruleServiceMock).should().removeRule(folderNodeRef, rule);
 | 
			
		||||
        then(ruleServiceMock).should().getRule(RULE_NODE_REF);
 | 
			
		||||
        then(ruleServiceMock).should().removeRule(FOLDER_NODE_REF, ruleModel);
 | 
			
		||||
        then(ruleServiceMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -525,7 +539,7 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
                    () -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
@@ -539,15 +553,15 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        for (Exception exception : ruleSetValidationExceptions())
 | 
			
		||||
        {
 | 
			
		||||
            Mockito.reset(nodeValidatorMock);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willThrow(exception);
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
                    () -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
            then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        }
 | 
			
		||||
@@ -559,28 +573,28 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
        for (Exception exception : ruleValidationExceptions())
 | 
			
		||||
        {
 | 
			
		||||
            Mockito.reset(nodeValidatorMock);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(folderNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(ruleSetNodeRef);
 | 
			
		||||
            given(nodeValidatorMock.validateFolderNode(any(), anyBoolean())).willReturn(FOLDER_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleSetNode(any(), any())).willReturn(RULE_SET_NODE_REF);
 | 
			
		||||
            given(nodeValidatorMock.validateRuleNode(any(), any())).willThrow(exception);
 | 
			
		||||
 | 
			
		||||
            // when
 | 
			
		||||
            assertThatExceptionOfType(exception.getClass()).isThrownBy(
 | 
			
		||||
                () -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
                    () -> rules.deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID));
 | 
			
		||||
 | 
			
		||||
            then(nodeValidatorMock).should().validateFolderNode(FOLDER_NODE_ID, true);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, folderNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleNode(RULE_ID, ruleSetNodeRef);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleSetNode(RULE_SET_ID, FOLDER_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).should().validateRuleNode(RULE_ID, RULE_SET_NODE_REF);
 | 
			
		||||
            then(nodeValidatorMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
            then(ruleServiceMock).shouldHaveNoInteractions();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static org.alfresco.service.cmr.rule.Rule createRule(final String id) {
 | 
			
		||||
    private static org.alfresco.service.cmr.rule.Rule createRule(final String id)
 | 
			
		||||
    {
 | 
			
		||||
        final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id);
 | 
			
		||||
        final org.alfresco.service.cmr.rule.Rule rule = new org.alfresco.service.cmr.rule.Rule();
 | 
			
		||||
        rule.setNodeRef(nodeRef);
 | 
			
		||||
        rule.setRuleType("ruleType");
 | 
			
		||||
        rule.setAction(action);
 | 
			
		||||
 | 
			
		||||
        return rule;
 | 
			
		||||
    }
 | 
			
		||||
@@ -588,27 +602,27 @@ public class RulesImplTest extends TestCase
 | 
			
		||||
    private static List<Exception> folderValidationExceptions()
 | 
			
		||||
    {
 | 
			
		||||
        return List.of(
 | 
			
		||||
            new EntityNotFoundException(FOLDER_NODE_ID),
 | 
			
		||||
            new InvalidArgumentException(),
 | 
			
		||||
            new PermissionDeniedException()
 | 
			
		||||
                new EntityNotFoundException(FOLDER_NODE_ID),
 | 
			
		||||
                new InvalidArgumentException(),
 | 
			
		||||
                new PermissionDeniedException()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static List<Exception> ruleSetValidationExceptions()
 | 
			
		||||
    {
 | 
			
		||||
        return List.of(
 | 
			
		||||
            new EntityNotFoundException(RULE_SET_ID),
 | 
			
		||||
            new InvalidArgumentException(),
 | 
			
		||||
            new RelationshipResourceNotFoundException(RULE_SET_ID, "fake-relationship-id")
 | 
			
		||||
                new EntityNotFoundException(RULE_SET_ID),
 | 
			
		||||
                new InvalidArgumentException(),
 | 
			
		||||
                new RelationshipResourceNotFoundException(RULE_SET_ID, "fake-relationship-id")
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static List<Exception> ruleValidationExceptions()
 | 
			
		||||
    {
 | 
			
		||||
        return List.of(
 | 
			
		||||
            new EntityNotFoundException(RULE_ID),
 | 
			
		||||
            new InvalidArgumentException(),
 | 
			
		||||
            new RelationshipResourceNotFoundException(RULE_ID, "fake-relationship-id")
 | 
			
		||||
                new EntityNotFoundException(RULE_ID),
 | 
			
		||||
                new InvalidArgumentException(),
 | 
			
		||||
                new RelationshipResourceNotFoundException(RULE_ID, "fake-relationship-id")
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,8 @@
 | 
			
		||||
package org.alfresco.rest.api.model.rules;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.mockito.BDDMockito.then;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@@ -34,15 +36,18 @@ import java.util.List;
 | 
			
		||||
import org.alfresco.repo.action.ActionConditionImpl;
 | 
			
		||||
import org.alfresco.repo.action.ActionImpl;
 | 
			
		||||
import org.alfresco.repo.action.executer.ScriptActionExecuter;
 | 
			
		||||
import org.alfresco.rest.api.Nodes;
 | 
			
		||||
import org.alfresco.service.Experimental;
 | 
			
		||||
import org.alfresco.service.cmr.action.Action;
 | 
			
		||||
import org.alfresco.service.cmr.action.ActionCondition;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.StoreRef;
 | 
			
		||||
import org.alfresco.service.cmr.rule.RuleType;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
@RunWith(MockitoJUnitRunner.class)
 | 
			
		||||
public class RuleTest
 | 
			
		||||
{
 | 
			
		||||
    private static final String RULE_ID = "fake-rule-id";
 | 
			
		||||
@@ -52,6 +57,7 @@ public class RuleTest
 | 
			
		||||
    private static final boolean RULE_CASCADE = true;
 | 
			
		||||
    private static final boolean RULE_ASYNC = true;
 | 
			
		||||
    private static final boolean RULE_SHARED = true;
 | 
			
		||||
    private static final String ACTION_DEFINITION_NAME = "action-def-name";
 | 
			
		||||
    private static final String ERROR_SCRIPT = "error-script-ref";
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -61,7 +67,7 @@ public class RuleTest
 | 
			
		||||
        final Rule expectedRule = createRuleWithDefaultValues();
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        final Rule actualRule = Rule.from(ruleModel, RULE_SHARED);
 | 
			
		||||
        final Rule actualRule = Rule.from(ruleModel);
 | 
			
		||||
 | 
			
		||||
        assertThat(actualRule).isNotNull().usingRecursiveComparison().isEqualTo(expectedRule);
 | 
			
		||||
 | 
			
		||||
@@ -74,12 +80,57 @@ public class RuleTest
 | 
			
		||||
        final Rule expectedRule = Rule.builder().enabled(true).create();
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        final Rule actualRule = Rule.from(ruleModel, false);
 | 
			
		||||
        final Rule actualRule = Rule.from(ruleModel);
 | 
			
		||||
 | 
			
		||||
        assertThat(actualRule).isNotNull().usingRecursiveComparison().isEqualTo(expectedRule);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testToServiceModel()
 | 
			
		||||
    {
 | 
			
		||||
        final Nodes nodesMock = mock(Nodes.class);
 | 
			
		||||
        final Rule rule = createRuleWithDefaultValues();
 | 
			
		||||
        rule.setActions(List.of(Action.builder().actionDefinitionId(ACTION_DEFINITION_NAME).create()));
 | 
			
		||||
        final org.alfresco.service.cmr.rule.Rule expectedRuleModel = createRuleModel();
 | 
			
		||||
        final org.alfresco.service.cmr.action.Action expectedCompensatingActionModel = createCompensatingActionModel();
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock);
 | 
			
		||||
 | 
			
		||||
        then(nodesMock).should().validateOrLookupNode(RULE_ID, null);
 | 
			
		||||
        then(nodesMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
        assertThat(actualRuleModel)
 | 
			
		||||
            .isNotNull()
 | 
			
		||||
            .usingRecursiveComparison().ignoringFields("nodeRef", "action")
 | 
			
		||||
            .isEqualTo(expectedRuleModel);
 | 
			
		||||
        assertThat(actualRuleModel.getAction())
 | 
			
		||||
            .isNotNull();
 | 
			
		||||
        assertThat(actualRuleModel.getAction().getCompensatingAction())
 | 
			
		||||
            .isNotNull()
 | 
			
		||||
            .usingRecursiveComparison().ignoringFields("id")
 | 
			
		||||
            .isEqualTo(expectedCompensatingActionModel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testToServiceModel_withNullValues()
 | 
			
		||||
    {
 | 
			
		||||
        final Nodes nodesMock = mock(Nodes.class);
 | 
			
		||||
        final Rule rule = new Rule();
 | 
			
		||||
        final org.alfresco.service.cmr.rule.Rule expectedRuleModel = new org.alfresco.service.cmr.rule.Rule();
 | 
			
		||||
        expectedRuleModel.setRuleDisabled(true);
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        final org.alfresco.service.cmr.rule.Rule actualRuleModel = rule.toServiceModel(nodesMock);
 | 
			
		||||
 | 
			
		||||
        then(nodesMock).shouldHaveNoInteractions();
 | 
			
		||||
        assertThat(actualRuleModel)
 | 
			
		||||
            .isNotNull()
 | 
			
		||||
            .usingRecursiveComparison()
 | 
			
		||||
            .ignoringFields("ruleTypes")
 | 
			
		||||
            .isEqualTo(expectedRuleModel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static org.alfresco.service.cmr.rule.Rule createRuleModel() {
 | 
			
		||||
        final NodeRef nodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, RULE_ID);
 | 
			
		||||
        final org.alfresco.service.cmr.rule.Rule ruleModel = new org.alfresco.service.cmr.rule.Rule(nodeRef);
 | 
			
		||||
@@ -89,17 +140,27 @@ public class RuleTest
 | 
			
		||||
        ruleModel.applyToChildren(RULE_CASCADE);
 | 
			
		||||
        ruleModel.setExecuteAsynchronously(RULE_ASYNC);
 | 
			
		||||
        ruleModel.setRuleTypes(List.of(RuleType.INBOUND, RuleType.UPDATE));
 | 
			
		||||
        final Action compensatingAction = new ActionImpl(nodeRef, "compensatingActionId", "compensatingActionDefName");
 | 
			
		||||
        compensatingAction.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, ERROR_SCRIPT);
 | 
			
		||||
        final ActionCondition actionCondition = new ActionConditionImpl("actionConditionId", "actionConditionDefName");
 | 
			
		||||
        final Action action = new ActionImpl(nodeRef, "actionId", "actionDefName");
 | 
			
		||||
        action.setCompensatingAction(compensatingAction);
 | 
			
		||||
        action.addActionCondition(actionCondition);
 | 
			
		||||
        ruleModel.setAction(action);
 | 
			
		||||
        ruleModel.setAction(createActionModel());
 | 
			
		||||
 | 
			
		||||
        return ruleModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static org.alfresco.service.cmr.action.Action createActionModel() {
 | 
			
		||||
        final ActionCondition actionCondition = new ActionConditionImpl("action-condition-id", "action-condition-def-name");
 | 
			
		||||
        final org.alfresco.service.cmr.action.Action actionModel = new ActionImpl(null, "action-id", ACTION_DEFINITION_NAME);
 | 
			
		||||
        actionModel.setCompensatingAction(createCompensatingActionModel());
 | 
			
		||||
        actionModel.addActionCondition(actionCondition);
 | 
			
		||||
 | 
			
		||||
        return actionModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static org.alfresco.service.cmr.action.Action createCompensatingActionModel() {
 | 
			
		||||
        final org.alfresco.service.cmr.action.Action compensatingActionModel = new ActionImpl(null, "compensating-action-id", ScriptActionExecuter.NAME);
 | 
			
		||||
        compensatingActionModel.setParameterValue(ScriptActionExecuter.PARAM_SCRIPTREF, ERROR_SCRIPT);
 | 
			
		||||
 | 
			
		||||
        return compensatingActionModel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static Rule createRuleWithDefaultValues() {
 | 
			
		||||
        return Rule.builder()
 | 
			
		||||
            .id(RULE_ID)
 | 
			
		||||
@@ -108,7 +169,6 @@ public class RuleTest
 | 
			
		||||
            .enabled(RULE_ENABLED)
 | 
			
		||||
            .cascade(RULE_CASCADE)
 | 
			
		||||
            .asynchronous(RULE_ASYNC)
 | 
			
		||||
            .shared(RULE_SHARED)
 | 
			
		||||
            .triggers(List.of(RuleTrigger.INBOUND, RuleTrigger.UPDATE))
 | 
			
		||||
            .errorScript(ERROR_SCRIPT)
 | 
			
		||||
            .conditions(CompositeCondition.from(Collections.emptyList()))
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,75 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Remote API
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *  GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.nodes;
 | 
			
		||||
 | 
			
		||||
import junit.framework.TestCase;
 | 
			
		||||
import org.alfresco.rest.api.RuleSets;
 | 
			
		||||
import org.alfresco.rest.api.model.rules.RuleSetLink;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
 | 
			
		||||
import org.junit.Assert;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.runner.RunWith;
 | 
			
		||||
import org.mockito.InjectMocks;
 | 
			
		||||
import org.mockito.Mock;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import static org.mockito.Mockito.when;
 | 
			
		||||
 | 
			
		||||
@RunWith(MockitoJUnitRunner.class)
 | 
			
		||||
public class NodeRuleSetsRelationTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    private static final String FOLDER_NODE_ID = "dummy-folder-node-id";
 | 
			
		||||
    private static final String LINK_TO_NODE_ID = "dummy-link-to-node-id";
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private RuleSets ruleSets;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private Parameters parameters;
 | 
			
		||||
 | 
			
		||||
    @InjectMocks
 | 
			
		||||
    private NodeRuleSetLinksRelation nodeRuleSetLinksRelation;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void shouldProperlyCreateLink()
 | 
			
		||||
    {
 | 
			
		||||
        RuleSetLink ruleSetLink = new RuleSetLink();
 | 
			
		||||
        List<RuleSetLink> ruleResult = List.of(ruleSetLink);
 | 
			
		||||
 | 
			
		||||
        RuleSetLink requestBody = new RuleSetLink();
 | 
			
		||||
        requestBody.setId(LINK_TO_NODE_ID);
 | 
			
		||||
 | 
			
		||||
        when(ruleSets.linkToRuleSet(FOLDER_NODE_ID, LINK_TO_NODE_ID)).thenReturn(ruleSetLink);
 | 
			
		||||
 | 
			
		||||
        List<RuleSetLink> actual = nodeRuleSetLinksRelation.create(FOLDER_NODE_ID,List.of(requestBody), parameters);
 | 
			
		||||
        Assert.assertEquals(ruleResult, actual);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -26,6 +26,10 @@
 | 
			
		||||
 | 
			
		||||
package org.alfresco.rest.api.nodes;
 | 
			
		||||
 | 
			
		||||
import static org.mockito.BDDMockito.then;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import junit.framework.TestCase;
 | 
			
		||||
import org.alfresco.rest.api.Rules;
 | 
			
		||||
import org.alfresco.rest.framework.resource.parameters.Paging;
 | 
			
		||||
@@ -40,17 +44,15 @@ import org.mockito.Mock;
 | 
			
		||||
import org.mockito.MockitoAnnotations;
 | 
			
		||||
import org.mockito.junit.MockitoJUnitRunner;
 | 
			
		||||
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.BDDMockito.then;
 | 
			
		||||
 | 
			
		||||
@Experimental
 | 
			
		||||
@RunWith(MockitoJUnitRunner.class)
 | 
			
		||||
public class NodeRulesRelationTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    private static final String FOLDER_NODE_ID = "dummy-node-id";
 | 
			
		||||
    private static final String RULE_SET_ID = "dummy-rule-set-id";
 | 
			
		||||
    private static final String RULE_ID = "dummy-rule-id";
 | 
			
		||||
    private static final List<String> INCLUDE = List.of("include-field");
 | 
			
		||||
    private static final Paging PAGING = Paging.DEFAULT;
 | 
			
		||||
 | 
			
		||||
    @Mock
 | 
			
		||||
    private Rules rulesMock;
 | 
			
		||||
@@ -68,35 +70,34 @@ public class NodeRulesRelationTest extends TestCase
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testReadAll()
 | 
			
		||||
    {
 | 
			
		||||
        final Paging paging = Paging.DEFAULT;
 | 
			
		||||
        final Parameters parameters = ParamsExtender.valueOf(paging, FOLDER_NODE_ID, RULE_SET_ID, null);
 | 
			
		||||
        final Parameters parameters = ParamsExtender.valueOf(PAGING, FOLDER_NODE_ID, RULE_SET_ID, null, INCLUDE);
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        nodeRulesRelation.readAll(FOLDER_NODE_ID, parameters);
 | 
			
		||||
 | 
			
		||||
        then(rulesMock).should().getRules(eq(FOLDER_NODE_ID), eq(RULE_SET_ID), eq(paging));
 | 
			
		||||
        then(rulesMock).should().getRules(FOLDER_NODE_ID, RULE_SET_ID, INCLUDE, PAGING);
 | 
			
		||||
        then(rulesMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testReadById()
 | 
			
		||||
    {
 | 
			
		||||
        final Parameters parameters = ParamsExtender.valueOf(null, FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
 | 
			
		||||
        final Parameters parameters = ParamsExtender.valueOf(null, FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE);
 | 
			
		||||
 | 
			
		||||
        // when
 | 
			
		||||
        nodeRulesRelation.readById(FOLDER_NODE_ID, RULE_SET_ID, parameters);
 | 
			
		||||
 | 
			
		||||
        then(rulesMock).should().getRuleById(eq(FOLDER_NODE_ID), eq(RULE_SET_ID), eq(RULE_ID));
 | 
			
		||||
        then(rulesMock).should().getRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE);
 | 
			
		||||
        then(rulesMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDeleteById() {
 | 
			
		||||
        final Parameters parameters = ParamsExtender.valueOf(null, FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
 | 
			
		||||
        final Parameters parameters = ParamsExtender.valueOf(null, FOLDER_NODE_ID, RULE_SET_ID, RULE_ID, INCLUDE);
 | 
			
		||||
        // when
 | 
			
		||||
        nodeRulesRelation.delete(FOLDER_NODE_ID, RULE_SET_ID, parameters);
 | 
			
		||||
 | 
			
		||||
        then(rulesMock).should().deleteRuleById(eq(FOLDER_NODE_ID), eq(RULE_SET_ID), eq(RULE_ID));
 | 
			
		||||
        then(rulesMock).should().deleteRuleById(FOLDER_NODE_ID, RULE_SET_ID, RULE_ID);
 | 
			
		||||
        then(rulesMock).shouldHaveNoMoreInteractions();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3721,6 +3721,50 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest
 | 
			
		||||
        getSingle(getNodeContentUrl(contentNodeId), null, null, headers, 304);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tests download of file/content name.
 | 
			
		||||
     * <p>GET:</p>
 | 
			
		||||
     * {@literal <host>:<port>/alfresco/api/-default-/public/alfresco/versions/1/nodes/<nodeId>/content}
 | 
			
		||||
     */
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDownloadFileContentName() throws Exception
 | 
			
		||||
    {
 | 
			
		||||
        setRequestContext(user1);
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // Test plain text
 | 
			
		||||
        //
 | 
			
		||||
 | 
			
		||||
        String fileName = "Test Download (1).txt";
 | 
			
		||||
        File file = getResourceFile(fileName);
 | 
			
		||||
 | 
			
		||||
        MultiPartBuilder multiPartBuilder = MultiPartBuilder.create()
 | 
			
		||||
                                                            .setFileData(new FileData(fileName, file));
 | 
			
		||||
        MultiPartRequest reqBody = multiPartBuilder.build();
 | 
			
		||||
 | 
			
		||||
        // Upload text content
 | 
			
		||||
        HttpResponse response = post(getNodeChildrenUrl(Nodes.PATH_MY), reqBody.getBody(), null, reqBody.getContentType(), 201);
 | 
			
		||||
        Document document = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
 | 
			
		||||
 | 
			
		||||
        String contentNodeId = document.getId();
 | 
			
		||||
 | 
			
		||||
        // Check the upload response
 | 
			
		||||
        assertEquals(fileName, document.getName());
 | 
			
		||||
        ContentInfo contentInfo = document.getContent();
 | 
			
		||||
        assertNotNull(contentInfo);
 | 
			
		||||
        assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, contentInfo.getMimeType());
 | 
			
		||||
 | 
			
		||||
        // Download text content - by default with Content-Disposition header
 | 
			
		||||
        response = getSingle(NodesEntityResource.class, contentNodeId + "/content", null, 200);
 | 
			
		||||
 | 
			
		||||
        String textContent = response.getResponse();
 | 
			
		||||
        assertEquals("The quick brown fox jumps over the lazy dog", textContent);
 | 
			
		||||
        Map<String, String> responseHeaders = response.getHeaders();
 | 
			
		||||
        assertNotNull(responseHeaders);
 | 
			
		||||
        assertEquals("attachment; filename=\"Test Download (1).txt\"; filename*=UTF-8''Test%20Download%20%281%29.txt", responseHeaders.get("Content-Disposition"));
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tests download of file/content using backed temp file for streaming.
 | 
			
		||||
     * <p>
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@ package org.alfresco.rest.framework.tests.core;
 | 
			
		||||
import static org.mockito.Mockito.mock;
 | 
			
		||||
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.rest.framework.jacksonextensions.BeanPropertiesFilter;
 | 
			
		||||
@@ -72,4 +73,9 @@ public class ParamsExtender extends Params
 | 
			
		||||
    {
 | 
			
		||||
        return new ParamsExtender(entityId, relationshipId, relationship2Id, null, null, null, new Params.RecognizedParams(null, paging, null, null, null, null, null, null, false));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Params valueOf(Paging paging, String entityId, String relationshipId, String relationship2Id, List<String> include)
 | 
			
		||||
    {
 | 
			
		||||
        return new ParamsExtender(entityId, relationshipId, relationship2Id, null, null, null, new Params.RecognizedParams(null, paging, null, null, include, null, null, null, false));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
The quick brown fox jumps over the lazy dog
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>org.alfresco</groupId>
 | 
			
		||||
        <artifactId>alfresco-community-repo</artifactId>
 | 
			
		||||
        <version>17.79</version>
 | 
			
		||||
        <version>17.102-SNAPSHOT</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
 | 
			
		||||
    <dependencies>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,28 +1,28 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Repository
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software. 
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of 
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is 
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 * 
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Repository
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.repo.exporter;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
@@ -39,6 +39,7 @@ import java.util.List;
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.model.ContentModel;
 | 
			
		||||
import org.alfresco.repo.node.MLPropertyInterceptor;
 | 
			
		||||
@@ -77,6 +78,7 @@ import org.alfresco.service.descriptor.DescriptorService;
 | 
			
		||||
import org.alfresco.service.namespace.NamespaceService;
 | 
			
		||||
import org.alfresco.service.namespace.QName;
 | 
			
		||||
import org.alfresco.service.namespace.RegexQNamePattern;
 | 
			
		||||
import org.apache.commons.lang3.math.NumberUtils;
 | 
			
		||||
import org.dom4j.io.OutputFormat;
 | 
			
		||||
import org.dom4j.io.XMLWriter;
 | 
			
		||||
import org.springframework.extensions.surf.util.ParameterCheck;
 | 
			
		||||
@@ -99,6 +101,8 @@ public class ExporterComponent
 | 
			
		||||
    private DescriptorService descriptorService;
 | 
			
		||||
    private AuthenticationService authenticationService;
 | 
			
		||||
    private PermissionService permissionService;
 | 
			
		||||
 | 
			
		||||
    private String exportChunkSize;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /** Indent Size */
 | 
			
		||||
@@ -178,6 +182,14 @@ public class ExporterComponent
 | 
			
		||||
    {
 | 
			
		||||
        this.exportSecondaryNodes = exportSecondaryNodes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param exportChunkSize  the exportChunkSize
 | 
			
		||||
     */
 | 
			
		||||
    public void setExportChunkSize(String exportChunkSize)
 | 
			
		||||
    {
 | 
			
		||||
        this.exportChunkSize = exportChunkSize;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /* (non-Javadoc)
 | 
			
		||||
     * @see org.alfresco.service.cmr.view.ExporterService#exportView(java.io.OutputStream, org.alfresco.service.cmr.view.ExporterCrawlerParameters, org.alfresco.service.cmr.view.Exporter)
 | 
			
		||||
@@ -943,28 +955,23 @@ public class ExporterComponent
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Current strategy is to determine if node is a child of the root exported node
 | 
			
		||||
                for (NodeRef exportRoot : context.getExportList())
 | 
			
		||||
                if (context.getExportMap() != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (nodeRef.equals(exportRoot) && parameters.isCrawlSelf() == true)
 | 
			
		||||
                    for (NodeRef[] listNodeRef : context.getExportMap().values())
 | 
			
		||||
                    {
 | 
			
		||||
                        // node to export is the root export node (and root is to be exported)
 | 
			
		||||
                        isWithin = true;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        // locate export root in primary parent path of node
 | 
			
		||||
                        Path nodePath = nodeService.getPath(nodeRef);
 | 
			
		||||
                        for (int i = nodePath.size() - 1; i >= 0; i--)
 | 
			
		||||
                        for (NodeRef exportRoot : listNodeRef)
 | 
			
		||||
                        {
 | 
			
		||||
                            Path.ChildAssocElement pathElement = (Path.ChildAssocElement) nodePath.get(i);
 | 
			
		||||
                            if (pathElement.getRef().getChildRef().equals(exportRoot))
 | 
			
		||||
                            {
 | 
			
		||||
                                isWithin = true;
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                            isWithin = checkIsWithin(nodeRef, exportRoot, parameters);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    for (NodeRef exportRoot : context.getExportList())
 | 
			
		||||
                    {
 | 
			
		||||
                        isWithin = checkIsWithin(nodeRef, exportRoot, parameters);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (AccessDeniedException accessErr)
 | 
			
		||||
            {
 | 
			
		||||
@@ -979,6 +986,28 @@ public class ExporterComponent
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean checkIsWithin(NodeRef nodeRef, NodeRef exportRoot, ExporterCrawlerParameters parameters){
 | 
			
		||||
        if (nodeRef.equals(exportRoot) && parameters.isCrawlSelf() == true)
 | 
			
		||||
        {
 | 
			
		||||
            // node to export is the root export node (and root is to be exported)
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // locate export root in primary parent path of node
 | 
			
		||||
            Path nodePath = nodeService.getPath(nodeRef);
 | 
			
		||||
            for (int i = nodePath.size() - 1; i >= 0; i--)
 | 
			
		||||
            {
 | 
			
		||||
                Path.ChildAssocElement pathElement = (Path.ChildAssocElement) nodePath.get(i);
 | 
			
		||||
                if (pathElement.getRef().getChildRef().equals(exportRoot))
 | 
			
		||||
                {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Exporter Context
 | 
			
		||||
@@ -986,7 +1015,9 @@ public class ExporterComponent
 | 
			
		||||
    private class ExporterContextImpl implements ExporterContext
 | 
			
		||||
    {
 | 
			
		||||
        private NodeRef[] exportList;
 | 
			
		||||
        private Map<Integer,NodeRef[]> exportListMap;
 | 
			
		||||
        private NodeRef[] parentList;
 | 
			
		||||
        private Map<Integer,NodeRef[]> parentListMap;
 | 
			
		||||
        private String exportedBy;
 | 
			
		||||
        private Date exportedDate;
 | 
			
		||||
        private String exporterVersion;
 | 
			
		||||
@@ -995,8 +1026,10 @@ public class ExporterComponent
 | 
			
		||||
        private Map<Integer, Set<NodeRef>> nodesWithAssociations = new HashMap<Integer, Set<NodeRef>>();
 | 
			
		||||
        
 | 
			
		||||
        private int index;
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        private int indexSubList;
 | 
			
		||||
        private int chunkSize;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Construct
 | 
			
		||||
         * 
 | 
			
		||||
@@ -1005,7 +1038,17 @@ public class ExporterComponent
 | 
			
		||||
        public ExporterContextImpl(ExporterCrawlerParameters parameters)
 | 
			
		||||
        {
 | 
			
		||||
            index = 0;
 | 
			
		||||
            
 | 
			
		||||
            indexSubList = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if(!NumberUtils.isParsable(exportChunkSize)){
 | 
			
		||||
                chunkSize = 10;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                chunkSize = Integer.parseInt(exportChunkSize);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // get current user performing export
 | 
			
		||||
            String currentUserName = authenticationService.getCurrentUserName();
 | 
			
		||||
            exportedBy = (currentUserName == null) ? "unknown" : currentUserName;
 | 
			
		||||
@@ -1022,24 +1065,80 @@ public class ExporterComponent
 | 
			
		||||
                NodeRef exportOf = getNodeRef(parameters.getExportFrom());
 | 
			
		||||
                exportList[0] = exportOf;
 | 
			
		||||
            }
 | 
			
		||||
            parentList = new NodeRef[exportList.length];
 | 
			
		||||
            for (int i = 0; i < exportList.length; i++)
 | 
			
		||||
            if(exportList.length > chunkSize)
 | 
			
		||||
            {
 | 
			
		||||
                parentList[i] = getParent(exportList[i], parameters.isCrawlSelf());
 | 
			
		||||
                exportListMap = splitArray(exportList);
 | 
			
		||||
 | 
			
		||||
                parentListMap = new HashMap<>();
 | 
			
		||||
                for(Map.Entry<Integer, NodeRef[]> exportEntrySet : exportListMap.entrySet())
 | 
			
		||||
                {
 | 
			
		||||
                    parentList= new NodeRef[exportEntrySet.getValue().length];
 | 
			
		||||
                    for (int i = 0; i < exportEntrySet.getValue().length; i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        parentList[i] = getParent(exportEntrySet.getValue()[i], parameters.isCrawlSelf());
 | 
			
		||||
                    }
 | 
			
		||||
                    parentListMap.put(exportEntrySet.getKey(), parentList);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            else{
 | 
			
		||||
                parentList = new NodeRef[exportList.length];
 | 
			
		||||
                for (int i = 0; i < exportList.length; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    parentList[i] = getParent(exportList[i], parameters.isCrawlSelf());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // get exporter version
 | 
			
		||||
            exporterVersion = descriptorService.getServerDescriptor().getVersion();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Map<Integer, NodeRef[]> splitArray(NodeRef[] arrayToSplit){
 | 
			
		||||
            if(chunkSize <= 0){
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            int rest = arrayToSplit.length % chunkSize;
 | 
			
		||||
            int chunks = arrayToSplit.length / chunkSize + (rest > 0 ? 1 : 0);
 | 
			
		||||
            Map<Integer, NodeRef[]> arrays = new HashMap<>() ;
 | 
			
		||||
            for(Integer i = 0; i < (rest > 0 ? chunks - 1 : chunks); i++){
 | 
			
		||||
                arrays.put(i, Arrays.copyOfRange(arrayToSplit, i * chunkSize, i * chunkSize + chunkSize));
 | 
			
		||||
            }
 | 
			
		||||
            if(rest > 0){
 | 
			
		||||
                arrays.put(chunks - 1, Arrays.copyOfRange(arrayToSplit, (chunks - 1) * chunkSize, (chunks - 1) * chunkSize + rest));
 | 
			
		||||
            }
 | 
			
		||||
            return arrays;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public boolean canRetrieve()
 | 
			
		||||
        {
 | 
			
		||||
            return index < exportList.length;
 | 
			
		||||
            if(exportListMap != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (exportListMap.containsKey(indexSubList))
 | 
			
		||||
                {
 | 
			
		||||
                    return index < exportListMap.get(indexSubList).length;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                return index < exportList.length;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public int setNextValue()
 | 
			
		||||
        {
 | 
			
		||||
            return ++index;
 | 
			
		||||
            if(exportListMap != null && (index == exportListMap.get(indexSubList).length-1)){
 | 
			
		||||
                resetContext();
 | 
			
		||||
                if(indexSubList <= exportListMap.size())
 | 
			
		||||
                {
 | 
			
		||||
                    ++indexSubList;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else{
 | 
			
		||||
                ++index;
 | 
			
		||||
            }
 | 
			
		||||
            return index;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public void resetContext()
 | 
			
		||||
@@ -1078,7 +1177,13 @@ public class ExporterComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (canRetrieve())
 | 
			
		||||
            {
 | 
			
		||||
                return exportList[index];
 | 
			
		||||
                if(exportListMap!=null)
 | 
			
		||||
                {
 | 
			
		||||
                    return exportListMap.get(indexSubList)[index];
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    return exportList[index];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1091,7 +1196,13 @@ public class ExporterComponent
 | 
			
		||||
        {
 | 
			
		||||
            if (canRetrieve())
 | 
			
		||||
            {
 | 
			
		||||
                return parentList[index];
 | 
			
		||||
                if(parentListMap!=null)
 | 
			
		||||
                {
 | 
			
		||||
                    return parentListMap.get(indexSubList)[index];
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    return parentList[index];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1105,6 +1216,11 @@ public class ExporterComponent
 | 
			
		||||
            return exportList;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Map<Integer, NodeRef[]> getExportMap()
 | 
			
		||||
        {
 | 
			
		||||
            return exportListMap;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * (non-Javadoc)
 | 
			
		||||
         * @see org.alfresco.service.cmr.view.ExporterContext#getExportParentList()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,31 +1,32 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Repository
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software. 
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of 
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is 
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 * 
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Repository
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.service.cmr.view;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
 | 
			
		||||
@@ -73,6 +74,8 @@ public interface ExporterContext
 | 
			
		||||
     * @return NodeRef[]
 | 
			
		||||
     */
 | 
			
		||||
    public NodeRef[] getExportList();
 | 
			
		||||
 | 
			
		||||
    public Map<Integer, NodeRef[]> getExportMap();
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets list of parents for exporting nodes
 | 
			
		||||
 
 | 
			
		||||
@@ -1,28 +1,28 @@
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Repository
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software. 
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of 
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is 
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 * 
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Repository
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software.
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of
 | 
			
		||||
 * the paid license agreement will prevail.  Otherwise, the software is
 | 
			
		||||
 * provided under the following open source license terms:
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Alfresco is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 * #L%
 | 
			
		||||
 */
 | 
			
		||||
package org.alfresco.service.cmr.view;
 | 
			
		||||
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
@@ -75,5 +75,6 @@ public interface ExporterService
 | 
			
		||||
     */
 | 
			
		||||
    @Auditable(parameters = {"exporter", "parameters", "progress"})
 | 
			
		||||
    public void exportView(Exporter exporter, ExporterCrawlerParameters parameters, Exporter progress);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    public void setExportChunkSize(String exportChunkSize);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -130,6 +130,9 @@
 | 
			
		||||
        <property name="permissionService">
 | 
			
		||||
            <ref bean="PermissionService" />
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="exportChunkSize">
 | 
			
		||||
            <value>${rm.export.chunk.size}</value>
 | 
			
		||||
        </property>
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
   <bean id="repositoryExporterComponent" class="org.alfresco.repo.exporter.RepositoryExporterComponent">
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 * #%L
 | 
			
		||||
 * Alfresco Repository
 | 
			
		||||
 * %%
 | 
			
		||||
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 | 
			
		||||
 * Copyright (C) 2005 - 2022 Alfresco Software Limited
 | 
			
		||||
 * %%
 | 
			
		||||
 * This file is part of the Alfresco software. 
 | 
			
		||||
 * If the software was purchased under a paid Alfresco license, the terms of 
 | 
			
		||||
@@ -33,7 +33,10 @@ import java.io.InputStream;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.io.BufferedReader;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Enumeration;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
@@ -41,6 +44,8 @@ import java.util.Iterator;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.zip.ZipEntry;
 | 
			
		||||
import java.util.zip.ZipFile;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.model.ContentModel;
 | 
			
		||||
import org.alfresco.repo.importer.ACPImportPackageHandler;
 | 
			
		||||
@@ -50,12 +55,7 @@ import org.alfresco.repo.security.permissions.PermissionServiceSPI;
 | 
			
		||||
import org.alfresco.service.ServiceRegistry;
 | 
			
		||||
import org.alfresco.service.cmr.model.FileFolderService;
 | 
			
		||||
import org.alfresco.service.cmr.model.FileInfo;
 | 
			
		||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.ContentData;
 | 
			
		||||
import org.alfresco.service.cmr.repository.MLText;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.NodeService;
 | 
			
		||||
import org.alfresco.service.cmr.repository.StoreRef;
 | 
			
		||||
import org.alfresco.service.cmr.repository.*;
 | 
			
		||||
import org.alfresco.service.cmr.search.CategoryService;
 | 
			
		||||
import org.alfresco.service.cmr.security.AccessPermission;
 | 
			
		||||
import org.alfresco.service.cmr.security.AccessStatus;
 | 
			
		||||
@@ -68,6 +68,7 @@ import org.alfresco.service.cmr.view.ExporterService;
 | 
			
		||||
import org.alfresco.service.cmr.view.ImportPackageHandler;
 | 
			
		||||
import org.alfresco.service.cmr.view.ImporterService;
 | 
			
		||||
import org.alfresco.service.cmr.view.Location;
 | 
			
		||||
 | 
			
		||||
import org.alfresco.service.namespace.QName;
 | 
			
		||||
import org.alfresco.service.transaction.TransactionService;
 | 
			
		||||
import org.alfresco.test_category.OwnJVMTestsCategory;
 | 
			
		||||
@@ -82,6 +83,7 @@ import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.junit.experimental.categories.Category;
 | 
			
		||||
import org.springframework.extensions.surf.util.I18NUtil;
 | 
			
		||||
import org.springframework.extensions.surf.util.InputStreamContent;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
 | 
			
		||||
@Category({OwnJVMTestsCategory.class, LuceneTests.class})
 | 
			
		||||
@@ -95,6 +97,7 @@ public class ExporterComponentTest extends BaseSpringTest
 | 
			
		||||
    private FileFolderService fileFolderService;
 | 
			
		||||
    private CategoryService categoryService;
 | 
			
		||||
    private TransactionService transactionService;
 | 
			
		||||
    private ContentService contentService;
 | 
			
		||||
    private StoreRef storeRef;
 | 
			
		||||
    private AuthenticationComponent authenticationComponent;
 | 
			
		||||
    private PermissionServiceSPI permissionService;
 | 
			
		||||
@@ -112,6 +115,7 @@ public class ExporterComponentTest extends BaseSpringTest
 | 
			
		||||
        categoryService = (CategoryService) applicationContext.getBean("categoryService");     
 | 
			
		||||
        transactionService = (TransactionService) applicationContext.getBean("transactionService");
 | 
			
		||||
        permissionService = (PermissionServiceSPI) applicationContext.getBean("permissionService");
 | 
			
		||||
        contentService = (ContentService) applicationContext.getBean("contentService");
 | 
			
		||||
 | 
			
		||||
        this.authenticationService = (MutableAuthenticationService) applicationContext.getBean("AuthenticationService");
 | 
			
		||||
        this.authenticationComponent = (AuthenticationComponent) applicationContext.getBean("authenticationComponent");
 | 
			
		||||
@@ -151,9 +155,7 @@ public class ExporterComponentTest extends BaseSpringTest
 | 
			
		||||
        OutputStream output = new FileOutputStream(tempFile);
 | 
			
		||||
        ExporterCrawlerParameters parameters = new ExporterCrawlerParameters();
 | 
			
		||||
        parameters.setExportFrom(location);
 | 
			
		||||
//        parameters.setExcludeAspects(new QName[] { ContentModel.ASPECT_AUDITABLE });
 | 
			
		||||
//        parameters.setExcludeChildAssocs(new QName[] { ContentModel.ASSOC_CONTAINS });
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        File acpFile = TempFileProvider.createTempFile("alf", ACPExportPackageHandler.ACP_EXTENSION);
 | 
			
		||||
        File dataFile = new File("test");
 | 
			
		||||
        File contentDir = new File("test");
 | 
			
		||||
@@ -162,6 +164,81 @@ public class ExporterComponentTest extends BaseSpringTest
 | 
			
		||||
        acpHandler.setExportAsFolders(true);
 | 
			
		||||
        exporterService.exportView(acpHandler, parameters, testProgress);
 | 
			
		||||
        output.close();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportWithChunkedList()
 | 
			
		||||
            throws Exception
 | 
			
		||||
    {
 | 
			
		||||
        TestProgress testProgress = new TestProgress();
 | 
			
		||||
        Location location = new Location(storeRef);
 | 
			
		||||
 | 
			
		||||
        String testFile = "_testFile";
 | 
			
		||||
        int numberOfNodesToExport = 20;
 | 
			
		||||
        // now export
 | 
			
		||||
        location.setPath("/system");
 | 
			
		||||
        File tempFile = TempFileProvider.createTempFile("xmlexporttest", ".xml");
 | 
			
		||||
        OutputStream output = new FileOutputStream(tempFile);
 | 
			
		||||
        ExporterCrawlerParameters parameters = new ExporterCrawlerParameters();
 | 
			
		||||
        parameters.setExportFrom(location);
 | 
			
		||||
 | 
			
		||||
        File acpFile = TempFileProvider.createTempFile("alf", ACPExportPackageHandler.ACP_EXTENSION);
 | 
			
		||||
        File dataFile = new File("test");
 | 
			
		||||
        File contentDir = new File("test");
 | 
			
		||||
        ACPExportPackageHandler acpHandler = new ACPExportPackageHandler(new FileOutputStream(acpFile), dataFile, contentDir, null);
 | 
			
		||||
        acpHandler.setNodeService(nodeService);
 | 
			
		||||
        acpHandler.setExportAsFolders(true);
 | 
			
		||||
        NodeRef nodeRef = (location == null) ? null : location.getNodeRef();
 | 
			
		||||
        if (nodeRef == null)
 | 
			
		||||
        {
 | 
			
		||||
            // If a specific node has not been provided, default to the root
 | 
			
		||||
            nodeRef = nodeService.getRootNode(location.getStoreRef());
 | 
			
		||||
        }
 | 
			
		||||
        NodeRef[] childRefs = new NodeRef[numberOfNodesToExport];
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < numberOfNodesToExport; i++)
 | 
			
		||||
        {
 | 
			
		||||
            Map<QName, Serializable> props = new HashMap<QName, Serializable>();
 | 
			
		||||
            props.put(ContentModel.PROP_NAME, this.getClass() + testFile + i);
 | 
			
		||||
            childRefs[i] = nodeService.createNode(nodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS, ContentModel.TYPE_CONTENT, props).getChildRef();
 | 
			
		||||
        }
 | 
			
		||||
        parameters.getExportFrom().setNodeRefs(childRefs);
 | 
			
		||||
        parameters.setCrawlSelf(true);
 | 
			
		||||
        exporterService.setExportChunkSize("3");
 | 
			
		||||
        exporterService.exportView(acpHandler, parameters, testProgress);
 | 
			
		||||
        output.close();
 | 
			
		||||
        ZipFile zipFile = new ZipFile(acpFile.getAbsolutePath());
 | 
			
		||||
 | 
			
		||||
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
 | 
			
		||||
        int numberOfExportedNodes = 0;
 | 
			
		||||
        while(entries.hasMoreElements()){
 | 
			
		||||
            ZipEntry entry = entries.nextElement();
 | 
			
		||||
            InputStream stream = zipFile.getInputStream(entry);
 | 
			
		||||
            try (BufferedReader br = new BufferedReader(new InputStreamReader(
 | 
			
		||||
                    stream, StandardCharsets.UTF_8));) {
 | 
			
		||||
 | 
			
		||||
                String line;
 | 
			
		||||
 | 
			
		||||
                while ((line = br.readLine()) != null) {
 | 
			
		||||
 | 
			
		||||
                    if(line.contains(testFile)){
 | 
			
		||||
                        numberOfExportedNodes++;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            stream.close();
 | 
			
		||||
        }
 | 
			
		||||
        zipFile.close();
 | 
			
		||||
 | 
			
		||||
        assertEquals(numberOfNodesToExport, numberOfExportedNodes);
 | 
			
		||||
 | 
			
		||||
        parameters.getExportFrom().setNodeRefs(null);
 | 
			
		||||
        for (int i = 0; i < numberOfNodesToExport; i++)
 | 
			
		||||
        {
 | 
			
		||||
            nodeService.deleteNode(childRefs[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user