mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-10 14:11:58 +00:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
146b59a4a8 | ||
|
2c3845bf9d | ||
|
dd05f3d338 | ||
|
c2338bdeb2 | ||
|
589e14a0b1 | ||
|
0f753c11c7 | ||
|
c8fea93298 | ||
|
d7f881ce0c | ||
|
b5fabb1290 | ||
|
f6d3ff4b15 | ||
|
2eb5bb7b7a | ||
|
53909dc086 | ||
|
4fedf0bada | ||
|
9f6edc648e | ||
|
22298eaa46 | ||
|
2e9db406d4 | ||
|
8565c9413e | ||
|
0d411cd759 | ||
|
ca3bbf5226 | ||
|
e83cd86c4d | ||
|
7da314cd97 | ||
|
d39401a7ec | ||
|
05df8a7582 | ||
|
85f22cb6e4 | ||
|
ce77b1ff42 | ||
|
29a7de55d2 | ||
|
cb3cb85694 | ||
|
2fcf1bd2d5 | ||
|
4c687f670e |
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -1,3 +1,3 @@
|
||||
SOLR6_TAG=2.0.7-A2
|
||||
SOLR6_TAG=2.0.7-A5
|
||||
POSTGRES_TAG=14.4
|
||||
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
|
@@ -38,9 +38,7 @@ tags:
|
||||
description: Retrieve and manage unfiled records containers
|
||||
- name: unfiled-record-folders
|
||||
description: Retrieve and manage unfiled record folders
|
||||
- name: events
|
||||
description: Retrieve and manage retention events
|
||||
|
||||
|
||||
paths:
|
||||
## GS sites
|
||||
'/gs-sites':
|
||||
@@ -2094,172 +2092,8 @@ paths:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
'/events':
|
||||
get:
|
||||
tags:
|
||||
- events
|
||||
summary: List all available retention events
|
||||
description: |
|
||||
Gets the list of events that can be used by retention steps
|
||||
operationId: getAllEvents
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- $ref: '#/parameters/skipCountParam'
|
||||
- $ref: '#/parameters/maxItemsParam'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/EventPaging'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: value of **maxItems** or **skipCount** is invalid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
|
||||
post:
|
||||
tags:
|
||||
- events
|
||||
summary: Create a new retention event
|
||||
description: |
|
||||
Creates a new event that can be used by retention schedules.
|
||||
operationId: createEvent
|
||||
parameters:
|
||||
- in: body
|
||||
name: eventBodyCreate
|
||||
description: The new event.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/EventBody'
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
'201':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/EventEntry'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: **name** or **type** is invalid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to create event
|
||||
'409':
|
||||
description: Cannot create event. An event with the name **name** already exists
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
|
||||
'/events/{eventId}':
|
||||
get:
|
||||
tags:
|
||||
- events
|
||||
summary: Return event for given eventId
|
||||
description: |
|
||||
Gets information about the retention event with id **eventId**.
|
||||
operationId: getEvent
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- $ref: '#/parameters/eventIdParam'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/EventEntry'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: **eventId** is invalid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'404':
|
||||
description: "**eventId** does not exist"
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
put:
|
||||
tags:
|
||||
- events
|
||||
summary: Update event for given eventId
|
||||
operationId: updateEvent
|
||||
description: |
|
||||
Updates retention event with id **eventId**.
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- $ref: '#/parameters/eventIdParam'
|
||||
- in: body
|
||||
name: eventBodyUpdate
|
||||
description: The event information to update.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/EventBody'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/EventEntry'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: The update request is invalid or **eventId** is not a valid format or **eventBodyUpdate** is invalid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
'403':
|
||||
description: Current user does not have permission to update events
|
||||
'404':
|
||||
description: "**eventId** does not exist"
|
||||
'409':
|
||||
description: Cannot update event. An event with the name **name** already exists
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
|
||||
'/event-types':
|
||||
get:
|
||||
tags:
|
||||
- events
|
||||
summary: List all the retention event types
|
||||
description: |
|
||||
Gets a list of all the retention event types.
|
||||
operationId: getAllEventTypes
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- $ref: '#/parameters/skipCountParam'
|
||||
- $ref: '#/parameters/maxItemsParam'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
schema:
|
||||
$ref: '#/definitions/EventTypePaging'
|
||||
'400':
|
||||
description: |
|
||||
Invalid parameter: value of **maxItems** or **skipCount** is invalid
|
||||
'401':
|
||||
description: Authentication failed
|
||||
default:
|
||||
description: Unexpected error
|
||||
schema:
|
||||
$ref: '#/definitions/Error'
|
||||
parameters:
|
||||
## event
|
||||
eventIdParam:
|
||||
name: eventId
|
||||
in: path
|
||||
description: The identifier of an event.
|
||||
required: true
|
||||
type: string
|
||||
## File plans
|
||||
filePlanEntryIncludeParam:
|
||||
name: include
|
||||
@@ -3927,92 +3761,4 @@ definitions:
|
||||
- SiteConsumer
|
||||
- SiteCollaborator
|
||||
- SiteContributor
|
||||
- SiteManager
|
||||
EventPaging:
|
||||
type: object
|
||||
properties:
|
||||
list:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
$ref: '#/definitions/Pagination'
|
||||
entries:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/EventEntry'
|
||||
EventEntry:
|
||||
type: object
|
||||
required:
|
||||
- entry
|
||||
properties:
|
||||
entry:
|
||||
$ref: '#/definitions/Event'
|
||||
Event:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- type
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: this is the id of the event
|
||||
name:
|
||||
type: string
|
||||
description: This is the unique display label of the event
|
||||
type:
|
||||
type: string
|
||||
description: this is event type
|
||||
EventBody:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: This is the unique display label of the event
|
||||
type:
|
||||
type: string
|
||||
description: this is event type
|
||||
default: Simple
|
||||
EventTypePaging:
|
||||
type: object
|
||||
properties:
|
||||
list:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
$ref: '#/definitions/Pagination'
|
||||
entries:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/EventTypeEntry'
|
||||
EventTypeEntry:
|
||||
type: object
|
||||
required:
|
||||
- entry
|
||||
properties:
|
||||
entry:
|
||||
$ref: '#/definitions/EventType'
|
||||
EventType:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: this is the event type id
|
||||
name:
|
||||
type: string
|
||||
description: this is event type name
|
||||
isAutomatic:
|
||||
type: boolean
|
||||
description: Whether events of this type need completing manually or can be completed automatically
|
||||
default: true
|
||||
associationName:
|
||||
type: string
|
||||
description: The association used to determine whether automatic events of this type are complete
|
||||
actionOnAssociatedNode:
|
||||
type: string
|
||||
description: If an association name is set for this event type then it is possible to require an action to be completed on the associated node
|
||||
- SiteManager
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -9,6 +9,6 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
</project>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -1,3 +1,3 @@
|
||||
SOLR6_TAG=2.0.7-A2
|
||||
SOLR6_TAG=2.0.7-A5
|
||||
POSTGRES_TAG=14.4
|
||||
ACTIVEMQ_TAG=5.17.1-jre11-rockylinux8
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<organization>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@@ -2,6 +2,7 @@ package org.alfresco.rest.tags;
|
||||
|
||||
import static org.alfresco.utility.data.RandomData.getRandomName;
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.util.Set;
|
||||
@@ -16,6 +17,11 @@ import org.alfresco.utility.testrail.annotation.TestRail;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.alfresco.utility.report.log.Step.STEP;
|
||||
|
||||
@Test(groups = {TestGroup.REQUIRE_SOLR})
|
||||
public class GetTagsTests extends TagsDataPrep
|
||||
{
|
||||
@@ -72,6 +78,138 @@ public class GetTagsTests extends TagsDataPrep
|
||||
.and().entriesListContains("tag", documentTagValue2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Include count in the query parameters and ensure count is as expected for returned tags.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withIncludeCount()
|
||||
{
|
||||
STEP("Get tags including count filter and ensure count is as expected for returned tags");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("include=count")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
|
||||
returnedCollection.getEntries().stream()
|
||||
.filter(e -> e.onModel().getTag().equals(folderTagValue) || e.onModel().getTag().equals(documentTagValue))
|
||||
.forEach(e -> e.onModel().assertThat().field("count").is(2));
|
||||
|
||||
returnedCollection.getEntries().stream()
|
||||
.filter(e -> e.onModel().getTag().equals(documentTagValue2))
|
||||
.forEach(e -> e.onModel().assertThat().field("count").is(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by count. Default sort order should be ascending
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByCountDefaultOrderShouldBeAsc()
|
||||
{
|
||||
STEP("Get tags and order results by count. Default sort order should be ascending");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("include=count&orderBy=count")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedAscBy("count");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by count in ascending order
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByCountAsc()
|
||||
{
|
||||
STEP("Get tags and order results by count in ascending order");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("include=count&orderBy=count ASC")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedAscBy("count");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by count in descending order
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByCountDesc()
|
||||
{
|
||||
STEP("Get tags and order results by count in descending order");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("include=count&orderBy=count DESC")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedDescBy("count");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by tag name. Default sort order should be ascending
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByTagDefaultOrderShouldBeAsc()
|
||||
{
|
||||
STEP("Get tags and order results by tag name. Default sort order should be ascending");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("orderBy=tag")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedAscBy("tag");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by tag name in ascending order
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByTagAsc()
|
||||
{
|
||||
STEP("Get tags and order results by tag name in ascending order");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("orderBy=tag ASC")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedAscBy("tag");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags and order results by tag name in descending order
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_withOrderByTagDesc()
|
||||
{
|
||||
STEP("Get tags and order results by tag name in descending order");
|
||||
returnedCollection = restClient.authenticateUser(adminUserModel)
|
||||
.withParams("orderBy=tag DESC")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(OK);
|
||||
returnedCollection.assertThat().entriesListIsSortedDescBy("tag");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that we get a 400 error when we request to order by count without also including the tag count.
|
||||
*/
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION })
|
||||
public void testGetTags_orderByCountWithoutIncludeCount()
|
||||
{
|
||||
restClient.authenticateUser(adminUserModel)
|
||||
.withParams("orderBy=count")
|
||||
.withCoreAPI()
|
||||
.getTags();
|
||||
|
||||
restClient.assertStatusCodeIs(BAD_REQUEST);
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY, description = "Failed authentication get tags call returns status code 401 with Manager role")
|
||||
@Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY })
|
||||
// @Bug(id="MNT-16904", description = "It fails only on environment with tenants")
|
||||
@@ -193,8 +331,7 @@ public class GetTagsTests extends TagsDataPrep
|
||||
.getPagination().assertThat().field("maxItems").is(100)
|
||||
.and().field("hasMoreItems").is("false")
|
||||
.and().field("count").is("0")
|
||||
.and().field("skipCount").is(20000)
|
||||
.and().field("totalItems").is(0);
|
||||
.and().field("skipCount").is(20000);
|
||||
}
|
||||
|
||||
@TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION,
|
||||
|
@@ -22,7 +22,8 @@ public class TagsDataPrep extends RestTest
|
||||
protected static ListUserWithRoles usersWithRoles;
|
||||
protected static SiteModel siteModel;
|
||||
protected static FileModel document;
|
||||
protected static FolderModel folder;
|
||||
protected static FolderModel folder, folder2;
|
||||
protected static RestTagModelsCollection folder2tags;
|
||||
protected static String documentTagValue, documentTagValue2, folderTagValue;
|
||||
protected static RestTagModel documentTag, documentTag2, folderTag, orphanTag, returnedModel;
|
||||
protected static RestTagModelsCollection returnedCollection;
|
||||
@@ -38,6 +39,7 @@ public class TagsDataPrep extends RestTest
|
||||
usersWithRoles = dataUser.usingAdmin().addUsersWithRolesToSite(siteModel, UserRole.SiteManager, UserRole.SiteCollaborator, UserRole.SiteConsumer, UserRole.SiteContributor);
|
||||
document = dataContent.usingUser(adminUserModel).usingSite(siteModel).createContent(CMISUtil.DocumentType.TEXT_PLAIN);
|
||||
folder = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
folder2 = dataContent.usingUser(adminUserModel).usingSite(siteModel).createFolder();
|
||||
|
||||
documentTagValue = RandomData.getRandomName("tag").toLowerCase();
|
||||
documentTagValue2 = RandomData.getRandomName("tag").toLowerCase();
|
||||
@@ -48,6 +50,7 @@ public class TagsDataPrep extends RestTest
|
||||
documentTag2 = restClient.withCoreAPI().usingResource(document).addTag(documentTagValue2);
|
||||
folderTag = restClient.withCoreAPI().usingResource(folder).addTag(folderTagValue);
|
||||
orphanTag = restClient.withCoreAPI().createSingleTag(RestTagModel.builder().tag(RandomData.getRandomName("orphan-tag").toLowerCase()).create());
|
||||
folder2tags = restClient.withCoreAPI().usingResource(folder2).addTags(folderTagValue, documentTagValue);
|
||||
|
||||
// Allow indexing to complete.
|
||||
Utility.sleep(500, 60000, () ->
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<developers>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
14
pom.xml
14
pom.xml
@@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Alfresco Community Repo Parent</name>
|
||||
|
||||
@@ -52,12 +52,12 @@
|
||||
<dependency.alfresco-messaging-repo.version>1.2.20</dependency.alfresco-messaging-repo.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>2.1.0-A6</dependency.alfresco-transform-service.version>
|
||||
<dependency.alfresco-transform-core.version>3.1.0-A8</dependency.alfresco-transform-core.version>
|
||||
<dependency.alfresco-transform-service.version>2.1.0-A9</dependency.alfresco-transform-service.version>
|
||||
<dependency.alfresco-transform-core.version>3.1.0-A12</dependency.alfresco-transform-core.version>
|
||||
<dependency.alfresco-greenmail.version>6.5</dependency.alfresco-greenmail.version>
|
||||
<dependency.acs-event-model.version>0.0.18</dependency.acs-event-model.version>
|
||||
|
||||
<dependency.spring.version>5.3.26</dependency.spring.version>
|
||||
<dependency.spring.version>5.3.27</dependency.spring.version>
|
||||
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
||||
<dependency.jackson.version>2.15.0-rc1</dependency.jackson.version>
|
||||
<dependency.cxf.version>3.5.5</dependency.cxf.version>
|
||||
@@ -111,8 +111,8 @@
|
||||
<dependency.json-smart.version>2.4.10</dependency.json-smart.version>
|
||||
<dependency.jakarta-rpc-api.version>1.1.4</dependency.jakarta-rpc-api.version>
|
||||
|
||||
<alfresco.googledrive.version>3.4.0-M1</alfresco.googledrive.version>
|
||||
<alfresco.aos-module.version>1.6.0-A4</alfresco.aos-module.version>
|
||||
<alfresco.googledrive.version>3.4.0-A4</alfresco.googledrive.version>
|
||||
<alfresco.aos-module.version>1.6.0-A5</alfresco.aos-module.version>
|
||||
<alfresco.api-explorer.version>7.3.0</alfresco.api-explorer.version> <!-- Also in alfresco-enterprise-share -->
|
||||
|
||||
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
||||
@@ -150,7 +150,7 @@
|
||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||
<tag>20.146</tag>
|
||||
<tag>20.155</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -36,6 +36,7 @@ import static org.alfresco.service.cmr.tagging.TaggingService.TAG_ROOT_NODE_REF;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -44,6 +45,8 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.ListBackedPagingResults;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tagging.NonExistentTagException;
|
||||
import org.alfresco.repo.tagging.TagExistsException;
|
||||
@@ -60,10 +63,12 @@ import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationE
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.framework.resource.parameters.SortColumn;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.Query;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryHelper;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.QueryImpl;
|
||||
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;
|
||||
@@ -81,40 +86,40 @@ import org.apache.commons.collections.CollectionUtils;
|
||||
*/
|
||||
public class TagsImpl implements Tags
|
||||
{
|
||||
public static final String PARAM_INCLUDE_COUNT = "count";
|
||||
private static final String PARAM_WHERE_TAG = "tag";
|
||||
static final String NOT_A_VALID_TAG = "An invalid parameter has been supplied";
|
||||
static final String NO_PERMISSION_TO_MANAGE_A_TAG = "Current user does not have permission to manage a tag";
|
||||
public static final String PARAM_INCLUDE_COUNT = "count";
|
||||
private static final String PARAM_WHERE_TAG = "tag";
|
||||
static final String NOT_A_VALID_TAG = "An invalid parameter has been supplied";
|
||||
static final String NO_PERMISSION_TO_MANAGE_A_TAG = "Current user does not have permission to manage a tag";
|
||||
|
||||
private Nodes nodes;
|
||||
private NodeService nodeService;
|
||||
private TaggingService taggingService;
|
||||
private TypeConstraint typeConstraint;
|
||||
private AuthorityService authorityService;
|
||||
private NodeService nodeService;
|
||||
private TaggingService taggingService;
|
||||
private TypeConstraint typeConstraint;
|
||||
private AuthorityService authorityService;
|
||||
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
public void setTypeConstraint(TypeConstraint typeConstraint)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
this.typeConstraint = typeConstraint;
|
||||
}
|
||||
|
||||
public void setNodes(Nodes nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
}
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setTaggingService(TaggingService taggingService)
|
||||
{
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
this.taggingService = taggingService;
|
||||
}
|
||||
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
public List<Tag> addTags(String nodeId, final List<Tag> tags, final Parameters parameters)
|
||||
{
|
||||
@@ -129,15 +134,15 @@ public class TagsImpl implements Tags
|
||||
{
|
||||
List<Pair<String, NodeRef>> tagNodeRefs = taggingService.addTags(nodeRef, tagValues);
|
||||
List<Tag> ret = new ArrayList<>(tags.size());
|
||||
List<Pair<String, Integer>> tagsCountPairList = taggingService.findTaggedNodesAndCountByTagName(nodeRef.getStoreRef());
|
||||
Map<String, Long> tagsCountMap = tagsCountPairList.stream().collect(Collectors.toMap(Pair::getFirst, pair -> Long.valueOf(pair.getSecond())));
|
||||
List<Pair<String, Integer>> tagsCountPairList = taggingService.findTaggedNodesAndCountByTagName(nodeRef.getStoreRef());
|
||||
Map<String, Long> tagsCountMap = tagsCountPairList.stream().collect(Collectors.toMap(Pair::getFirst, pair -> Long.valueOf(pair.getSecond())));
|
||||
for (Pair<String, NodeRef> pair : tagNodeRefs)
|
||||
{
|
||||
Tag createdTag = new Tag(pair.getSecond(), pair.getFirst());
|
||||
if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
createdTag.setCount(Optional.ofNullable(tagsCountMap.get(createdTag.getTag())).orElse(0L) + 1);
|
||||
}
|
||||
Tag createdTag = new Tag(pair.getSecond(), pair.getFirst());
|
||||
if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
createdTag.setCount(Optional.ofNullable(tagsCountMap.get(createdTag.getTag())).orElse(0L) + 1);
|
||||
}
|
||||
ret.add(createdTag);
|
||||
}
|
||||
return ret;
|
||||
@@ -147,120 +152,109 @@ public class TagsImpl implements Tags
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void deleteTag(String nodeId, String tagId)
|
||||
{
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
getTag(STORE_REF_WORKSPACE_SPACESSTORE, tagId, null);
|
||||
NodeRef existingTagNodeRef = validateTag(tagId);
|
||||
String tagValue = taggingService.getTagName(existingTagNodeRef);
|
||||
taggingService.removeTag(nodeRef, tagValue);
|
||||
NodeRef nodeRef = nodes.validateNode(nodeId);
|
||||
getTag(STORE_REF_WORKSPACE_SPACESSTORE, tagId, null);
|
||||
NodeRef existingTagNodeRef = validateTag(tagId);
|
||||
String tagValue = taggingService.getTagName(existingTagNodeRef);
|
||||
taggingService.removeTag(nodeRef, tagValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTagById(StoreRef storeRef, String tagId) {
|
||||
verifyAdminAuthority();
|
||||
public void deleteTagById(StoreRef storeRef, String tagId) {
|
||||
verifyAdminAuthority();
|
||||
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
taggingService.deleteTag(storeRef, tagValue);
|
||||
}
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagValue = taggingService.getTagName(tagNodeRef);
|
||||
taggingService.deleteTag(storeRef, tagValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionWithPagingInfo<Tag> getTags(StoreRef storeRef, Parameters params)
|
||||
{
|
||||
Paging paging = params.getPaging();
|
||||
Pair<String, Boolean> sorting = !params.getSorting().isEmpty() ? new Pair<>(params.getSorting().get(0).column, params.getSorting().get(0).asc) : null;
|
||||
Map<Integer, Collection<String>> namesFilters = resolveTagNamesQuery(params.getQuery());
|
||||
PagingResults<Pair<NodeRef, String>> results = taggingService.getTags(storeRef, Util.getPagingRequest(paging), namesFilters.get(EQUALS), namesFilters.get(MATCHES));
|
||||
|
||||
Integer totalItems = results.getTotalResultCount().getFirst();
|
||||
List<Pair<NodeRef, String>> page = results.getPage();
|
||||
List<Tag> tags = new ArrayList<>(page.size());
|
||||
for (Pair<NodeRef, String> pair : page)
|
||||
{
|
||||
Tag selectedTag = new Tag(pair.getFirst(), pair.getSecond());
|
||||
tags.add(selectedTag);
|
||||
}
|
||||
Map<NodeRef, Long> results = taggingService.getTags(storeRef, params.getInclude(), sorting, namesFilters.get(EQUALS), namesFilters.get(MATCHES));
|
||||
|
||||
List<Tag> tagsList = results.entrySet().stream().map(entry -> new Tag(entry.getKey(), (String)nodeService.getProperty(entry.getKey(), ContentModel.PROP_NAME))).collect(Collectors.toList());
|
||||
|
||||
if (params.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
List<Pair<String, Integer>> tagsByCount = taggingService.findTaggedNodesAndCountByTagName(storeRef);
|
||||
Map<String, Long> tagsByCountMap = new HashMap<>();
|
||||
if (tagsByCount != null)
|
||||
{
|
||||
for (Pair<String, Integer> tagByCountElem : tagsByCount)
|
||||
{
|
||||
tagsByCountMap.put(tagByCountElem.getFirst(), Long.valueOf(tagByCountElem.getSecond()));
|
||||
}
|
||||
}
|
||||
tags.forEach(tag -> tag.setCount(Optional.ofNullable(tagsByCountMap.get(tag.getTag())).orElse(0L)));
|
||||
tagsList.forEach(tag -> tag.setCount(results.get(tag.getNodeRef())));
|
||||
}
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, tags, results.hasMoreItems(), totalItems);
|
||||
ListBackedPagingResults listBackedPagingResults = new ListBackedPagingResults(tagsList, Util.getPagingRequest(params.getPaging()));
|
||||
|
||||
return CollectionWithPagingInfo.asPaged(paging, listBackedPagingResults.getPage(), listBackedPagingResults.hasMoreItems(), (Integer) listBackedPagingResults.getTotalResultCount().getFirst());
|
||||
}
|
||||
|
||||
public NodeRef validateTag(String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(tagId);
|
||||
return checkTagRootAsNodePrimaryParent(tagId, tagNodeRef);
|
||||
NodeRef tagNodeRef = nodes.validateNode(tagId);
|
||||
return checkTagRootAsNodePrimaryParent(tagId, tagNodeRef);
|
||||
}
|
||||
|
||||
public NodeRef validateTag(StoreRef storeRef, String tagId)
|
||||
{
|
||||
NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId);
|
||||
return checkTagRootAsNodePrimaryParent(tagId, tagNodeRef);
|
||||
NodeRef tagNodeRef = nodes.validateNode(storeRef, tagId);
|
||||
return checkTagRootAsNodePrimaryParent(tagId, tagNodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the number of times the given tag is used (if requested).
|
||||
*
|
||||
* @param storeRef The store the tag is in.
|
||||
* @param tagName The name of the tag.
|
||||
* @param parameters The request parameters object containing the includes parameter.
|
||||
* @return The number of times the tag is applied, or null if "count" wasn't in the include parameter.
|
||||
*/
|
||||
private Long findCountIfRequested(StoreRef storeRef, String tagName, Parameters parameters)
|
||||
{
|
||||
Long count = null;
|
||||
if (parameters != null && parameters.getInclude() != null && parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
count = taggingService.findCountByTagName(storeRef, tagName);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
/**
|
||||
* Find the number of times the given tag is used (if requested).
|
||||
*
|
||||
* @param storeRef The store the tag is in.
|
||||
* @param tagName The name of the tag.
|
||||
* @param parameters The request parameters object containing the includes parameter.
|
||||
* @return The number of times the tag is applied, or null if "count" wasn't in the include parameter.
|
||||
*/
|
||||
private Long findCountIfRequested(StoreRef storeRef, String tagName, Parameters parameters)
|
||||
{
|
||||
Long count = null;
|
||||
if (parameters != null && parameters.getInclude() != null && parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
count = taggingService.findCountByTagName(storeRef, tagName);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag changeTag(StoreRef storeRef, String tagId, Tag tag, Parameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef existingTagNodeRef = validateTag(storeRef, tagId);
|
||||
String existingTagName = taggingService.getTagName(existingTagNodeRef);
|
||||
Long count = findCountIfRequested(storeRef, existingTagName, parameters);
|
||||
String newTagName = tag.getTag();
|
||||
NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName);
|
||||
return Tag.builder().nodeRef(newTagNodeRef).tag(newTagName).count(count).create();
|
||||
}
|
||||
catch(NonExistentTagException e)
|
||||
{
|
||||
throw new NotFoundException(e.getMessage());
|
||||
}
|
||||
catch(TagExistsException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
catch(TaggingException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
try
|
||||
{
|
||||
NodeRef existingTagNodeRef = validateTag(storeRef, tagId);
|
||||
String existingTagName = taggingService.getTagName(existingTagNodeRef);
|
||||
Long count = findCountIfRequested(storeRef, existingTagName, parameters);
|
||||
String newTagName = tag.getTag();
|
||||
NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName);
|
||||
return Tag.builder().nodeRef(newTagNodeRef).tag(newTagName).count(count).create();
|
||||
}
|
||||
catch(NonExistentTagException e)
|
||||
{
|
||||
throw new NotFoundException(e.getMessage());
|
||||
}
|
||||
catch(TagExistsException e)
|
||||
{
|
||||
throw new ConstraintViolatedException(e.getMessage());
|
||||
}
|
||||
catch(TaggingException e)
|
||||
{
|
||||
throw new InvalidArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Tag getTag(StoreRef storeRef, String tagId, Parameters parameters)
|
||||
{
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagName = taggingService.getTagName(tagNodeRef);
|
||||
Long count = findCountIfRequested(storeRef, tagName, parameters);
|
||||
return Tag.builder().nodeRef(tagNodeRef).tag(tagName).count(count).create();
|
||||
NodeRef tagNodeRef = validateTag(storeRef, tagId);
|
||||
String tagName = taggingService.getTagName(tagNodeRef);
|
||||
Long count = findCountIfRequested(storeRef, tagName, parameters);
|
||||
return Tag.builder().nodeRef(tagNodeRef).tag(tagName).count(count).create();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -279,80 +273,80 @@ public class TagsImpl implements Tags
|
||||
return CollectionWithPagingInfo.asPaged(params.getPaging(), tags, results.hasMoreItems(), (totalItems == null ? null : totalItems.intValue()));
|
||||
}
|
||||
|
||||
@Experimental
|
||||
@Override
|
||||
public List<Tag> createTags(final StoreRef storeRef, final List<Tag> tags, final Parameters parameters)
|
||||
{
|
||||
verifyAdminAuthority();
|
||||
final List<String> tagNames = Optional.ofNullable(tags).orElse(Collections.emptyList()).stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(Tag::getTag)
|
||||
.distinct()
|
||||
.collect(toList());
|
||||
@Experimental
|
||||
@Override
|
||||
public List<Tag> createTags(final StoreRef storeRef, final List<Tag> tags, final Parameters parameters)
|
||||
{
|
||||
verifyAdminAuthority();
|
||||
final List<String> tagNames = Optional.ofNullable(tags).orElse(Collections.emptyList()).stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(Tag::getTag)
|
||||
.distinct()
|
||||
.collect(toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(tagNames))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_VALID_TAG);
|
||||
}
|
||||
if (CollectionUtils.isEmpty(tagNames))
|
||||
{
|
||||
throw new InvalidArgumentException(NOT_A_VALID_TAG);
|
||||
}
|
||||
|
||||
return taggingService.createTags(storeRef, tagNames).stream()
|
||||
.map(pair -> Tag.builder().tag(pair.getFirst()).nodeRef(pair.getSecond()).create())
|
||||
.peek(tag -> {
|
||||
if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
tag.setCount(0L);
|
||||
}
|
||||
}).collect(toList());
|
||||
}
|
||||
return taggingService.createTags(storeRef, tagNames).stream()
|
||||
.map(pair -> Tag.builder().tag(pair.getFirst()).nodeRef(pair.getSecond()).create())
|
||||
.peek(tag -> {
|
||||
if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
tag.setCount(0L);
|
||||
}
|
||||
}).collect(toList());
|
||||
}
|
||||
|
||||
private void verifyAdminAuthority()
|
||||
{
|
||||
if (!authorityService.hasAdminAuthority())
|
||||
{
|
||||
throw new PermissionDeniedException(NO_PERMISSION_TO_MANAGE_A_TAG);
|
||||
}
|
||||
}
|
||||
private void verifyAdminAuthority()
|
||||
{
|
||||
if (!authorityService.hasAdminAuthority())
|
||||
{
|
||||
throw new PermissionDeniedException(NO_PERMISSION_TO_MANAGE_A_TAG);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method resolves where query looking for clauses: EQUALS, IN or MATCHES.
|
||||
* Expected values for EQUALS and IN will be merged under EQUALS clause.
|
||||
* @param namesQuery Where query with expected tag name(s).
|
||||
* @return Map of expected exact and alike tag names.
|
||||
*/
|
||||
private Map<Integer, Collection<String>> resolveTagNamesQuery(final Query namesQuery)
|
||||
{
|
||||
if (namesQuery == null || namesQuery == QueryImpl.EMPTY)
|
||||
{
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
/**
|
||||
* Method resolves where query looking for clauses: EQUALS, IN or MATCHES.
|
||||
* Expected values for EQUALS and IN will be merged under EQUALS clause.
|
||||
* @param namesQuery Where query with expected tag name(s).
|
||||
* @return Map of expected exact and alike tag names.
|
||||
*/
|
||||
private Map<Integer, Collection<String>> resolveTagNamesQuery(final Query namesQuery)
|
||||
{
|
||||
if (namesQuery == null || namesQuery == QueryImpl.EMPTY)
|
||||
{
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
final Map<Integer, Collection<String>> properties = QueryHelper
|
||||
.resolve(namesQuery)
|
||||
.usingOrOperator()
|
||||
.withoutNegations()
|
||||
.getProperty(PARAM_WHERE_TAG)
|
||||
.getExpectedValuesForAnyOf(EQUALS, IN, MATCHES)
|
||||
.skipNegated();
|
||||
final Map<Integer, Collection<String>> properties = QueryHelper
|
||||
.resolve(namesQuery)
|
||||
.usingOrOperator()
|
||||
.withoutNegations()
|
||||
.getProperty(PARAM_WHERE_TAG)
|
||||
.getExpectedValuesForAnyOf(EQUALS, IN, MATCHES)
|
||||
.skipNegated();
|
||||
|
||||
return properties.entrySet().stream()
|
||||
.collect(Collectors.groupingBy((entry) -> {
|
||||
if (entry.getKey() == EQUALS || entry.getKey() == IN)
|
||||
{
|
||||
return EQUALS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MATCHES;
|
||||
}
|
||||
}, Collectors.flatMapping((entry) -> entry.getValue().stream().map(String::toLowerCase), Collectors.toCollection(HashSet::new))));
|
||||
}
|
||||
return properties.entrySet().stream()
|
||||
.collect(Collectors.groupingBy((entry) -> {
|
||||
if (entry.getKey() == EQUALS || entry.getKey() == IN)
|
||||
{
|
||||
return EQUALS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MATCHES;
|
||||
}
|
||||
}, Collectors.flatMapping((entry) -> entry.getValue().stream().map(String::toLowerCase), Collectors.toCollection(HashSet::new))));
|
||||
}
|
||||
|
||||
private NodeRef checkTagRootAsNodePrimaryParent(String tagId, NodeRef tagNodeRef)
|
||||
{
|
||||
if ( tagNodeRef == null || !nodeService.getPrimaryParent(tagNodeRef).getParentRef().equals(TAG_ROOT_NODE_REF))
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
private NodeRef checkTagRootAsNodePrimaryParent(String tagId, NodeRef tagNodeRef)
|
||||
{
|
||||
if ( tagNodeRef == null || !nodeService.getPrimaryParent(tagNodeRef).getParentRef().equals(TAG_ROOT_NODE_REF))
|
||||
{
|
||||
throw new EntityNotFoundException(tagId);
|
||||
}
|
||||
return tagNodeRef;
|
||||
}
|
||||
}
|
||||
|
@@ -29,7 +29,6 @@ import static java.util.stream.Collectors.toList;
|
||||
|
||||
import static org.alfresco.rest.api.impl.TagsImpl.NOT_A_VALID_TAG;
|
||||
import static org.alfresco.rest.api.impl.TagsImpl.NO_PERMISSION_TO_MANAGE_A_TAG;
|
||||
import static org.alfresco.rest.api.impl.TagsImpl.PARAM_INCLUDE_COUNT;
|
||||
import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.catchThrowable;
|
||||
@@ -41,10 +40,14 @@ import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.rest.api.Nodes;
|
||||
@@ -56,6 +59,7 @@ import org.alfresco.rest.framework.core.exceptions.UnsupportedResourceOperationE
|
||||
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
|
||||
import org.alfresco.rest.framework.resource.parameters.Paging;
|
||||
import org.alfresco.rest.framework.resource.parameters.Parameters;
|
||||
import org.alfresco.rest.framework.resource.parameters.SortColumn;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException;
|
||||
import org.alfresco.rest.framework.tools.RecognizedParamsExtractor;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
@@ -84,6 +88,8 @@ public class TagsImplTest
|
||||
private static final NodeRef TAG_PARENT_NODE_REF = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, PARENT_NODE_ID);
|
||||
private static final String CONTENT_NODE_ID = "content-node-id";
|
||||
private static final NodeRef CONTENT_NODE_REF = new NodeRef(STORE_REF_WORKSPACE_SPACESSTORE, CONTENT_NODE_ID);
|
||||
private static final String PARAM_INCLUDE_COUNT = "count";
|
||||
|
||||
|
||||
private final RecognizedParamsExtractor queryExtractor = new RecognizedParamsExtractor() {};
|
||||
|
||||
@@ -123,13 +129,16 @@ public class TagsImplTest
|
||||
public void testGetTags()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(PagingRequest.class), any(), any())).willReturn(pagingResultsMock);
|
||||
given(pagingResultsMock.getTotalResultCount()).willReturn(new Pair<>(Integer.MAX_VALUE, 0));
|
||||
given(pagingResultsMock.getPage()).willReturn(List.of(new Pair<>(TAG_NODE_REF, TAG_NAME)));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(new ArrayList<>());
|
||||
|
||||
//given(taggingServiceMock.getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(), any(), isNull(), isNull())).willReturn(List.of(new Pair<>(TAG_NODE_REF, null)));
|
||||
given(taggingServiceMock.getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(), any(), isNull(), isNull())).willReturn(Map.of(TAG_NODE_REF, 0L));
|
||||
given(nodeServiceMock.getProperty(any(NodeRef.class), eq(ContentModel.PROP_NAME))).willReturn("tag-dummy-name");
|
||||
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(PagingRequest.class), isNull(), isNull());
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(), any(), isNull(), isNull());
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(List.of(TAG_NAME));
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
@@ -139,14 +148,15 @@ public class TagsImplTest
|
||||
public void testGetTags_verifyIfCountIsZero()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(PagingRequest.class), any(), any())).willReturn(pagingResultsMock);
|
||||
given(pagingResultsMock.getTotalResultCount()).willReturn(new Pair<>(Integer.MAX_VALUE, 0));
|
||||
given(pagingResultsMock.getPage()).willReturn(List.of(new Pair<>(TAG_NODE_REF, TAG_NAME)));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(List.of(PARAM_INCLUDE_COUNT));
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(), any(), any(), any())).willReturn(Map.of(TAG_NODE_REF, 0L));
|
||||
|
||||
given(nodeServiceMock.getProperty(any(NodeRef.class), eq(ContentModel.PROP_NAME))).willReturn("tag-dummy-name");
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().findTaggedNodesAndCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE);
|
||||
final List<Tag> expectedTags = createTagsWithNodeRefs(List.of(TAG_NAME)).stream()
|
||||
.peek(tag -> tag.setCount(0L))
|
||||
.collect(toList());
|
||||
@@ -159,36 +169,157 @@ public class TagsImplTest
|
||||
{
|
||||
NodeRef tagNodeA = new NodeRef("tag://A/");
|
||||
NodeRef tagNodeB = new NodeRef("tag://B/");
|
||||
List<Pair<NodeRef, String>> tagPairs = List.of(new Pair<>(tagNodeA, "taga"), new Pair<>(tagNodeB, "tagb"));
|
||||
|
||||
given(parametersMock.getSorting()).willReturn(Collections.emptyList());
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(PagingRequest.class), any(), any())).willReturn(pagingResultsMock);
|
||||
given(pagingResultsMock.getTotalResultCount()).willReturn(new Pair<>(Integer.MAX_VALUE, 0));
|
||||
given(pagingResultsMock.getPage()).willReturn(tagPairs);
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
// Only taga is included in the returned list since tagb is not in use.
|
||||
given(taggingServiceMock.findTaggedNodesAndCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE)).willReturn(List.of(new Pair<>("taga", 5)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagNodeA, 5L);
|
||||
results.put(tagNodeB, 0L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), eq(List.of(PARAM_INCLUDE_COUNT)), isNull(), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(any(NodeRef.class), eq(ContentModel.PROP_NAME))).willReturn("taga", "tagb");
|
||||
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().findTaggedNodesAndCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE);
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("tagA").nodeRef(tagNodeA).count(5L).create(),
|
||||
Tag.builder().tag("tagB").nodeRef(tagNodeB).count(0L).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_orderByCountAscendingOrder()
|
||||
{
|
||||
NodeRef tagNodeA = new NodeRef("tag://A/");
|
||||
NodeRef tagNodeB = new NodeRef("tag://B/");
|
||||
NodeRef tagNodeC = new NodeRef("tag://C/");
|
||||
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
given(parametersMock.getSorting()).willReturn(List.of(new SortColumn("count", true)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagNodeB, 0L);
|
||||
results.put(tagNodeC, 2L);
|
||||
results.put(tagNodeA, 5L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), eq(List.of(PARAM_INCLUDE_COUNT)), eq(new Pair<>("count", true)), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(tagNodeA, ContentModel.PROP_NAME)).willReturn("taga");
|
||||
given(nodeServiceMock.getProperty(tagNodeB, ContentModel.PROP_NAME)).willReturn("tagb");
|
||||
given(nodeServiceMock.getProperty(tagNodeC, ContentModel.PROP_NAME)).willReturn("tagc");
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("tagb").nodeRef(tagNodeB).count(0L).create(),
|
||||
Tag.builder().tag("tagc").nodeRef(tagNodeC).count(2L).create(),
|
||||
Tag.builder().tag("taga").nodeRef(tagNodeA).count(5L).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_orderByCountDescendingOrder()
|
||||
{
|
||||
NodeRef tagNodeA = new NodeRef("tag://A/");
|
||||
NodeRef tagNodeB = new NodeRef("tag://B/");
|
||||
NodeRef tagNodeC = new NodeRef("tag://C/");
|
||||
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(List.of("count"));
|
||||
given(parametersMock.getSorting()).willReturn(List.of(new SortColumn("count", false)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagNodeA, 5L);
|
||||
results.put(tagNodeC, 2L);
|
||||
results.put(tagNodeB, 0L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), eq(List.of(PARAM_INCLUDE_COUNT)), eq(new Pair<>("count", false)), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(tagNodeA, ContentModel.PROP_NAME)).willReturn("taga");
|
||||
given(nodeServiceMock.getProperty(tagNodeB, ContentModel.PROP_NAME)).willReturn("tagb");
|
||||
given(nodeServiceMock.getProperty(tagNodeC, ContentModel.PROP_NAME)).willReturn("tagc");
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("taga").nodeRef(tagNodeA).count(5L).create(),
|
||||
Tag.builder().tag("tagc").nodeRef(tagNodeC).count(2L).create(),
|
||||
Tag.builder().tag("tagb").nodeRef(tagNodeB).count(0L).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_orderByTagAscendingOrder()
|
||||
{
|
||||
NodeRef tagApple = new NodeRef("tag://apple/");
|
||||
NodeRef tagBanana = new NodeRef("tag://banana/");
|
||||
NodeRef tagCoconut = new NodeRef("tag://coconut/");
|
||||
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(Collections.emptyList());
|
||||
given(parametersMock.getSorting()).willReturn(List.of(new SortColumn("tag", true)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagApple, 0L);
|
||||
results.put(tagBanana, 0L);
|
||||
results.put(tagCoconut, 0L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(), eq(new Pair<>("tag", true)), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(tagApple, ContentModel.PROP_NAME)).willReturn("apple");
|
||||
given(nodeServiceMock.getProperty(tagBanana, ContentModel.PROP_NAME)).willReturn("banana");
|
||||
given(nodeServiceMock.getProperty(tagCoconut, ContentModel.PROP_NAME)).willReturn("coconut");
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("apple").nodeRef(tagApple).create(),
|
||||
Tag.builder().tag("banana").nodeRef(tagBanana).create(),
|
||||
Tag.builder().tag("coconut").nodeRef(tagCoconut).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_orderByTagDescendingOrder()
|
||||
{
|
||||
NodeRef tagApple = new NodeRef("tag://apple/");
|
||||
NodeRef tagBanana = new NodeRef("tag://banana/");
|
||||
NodeRef tagCoconut = new NodeRef("tag://coconut/");
|
||||
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getInclude()).willReturn(Collections.emptyList());
|
||||
given(parametersMock.getSorting()).willReturn(List.of(new SortColumn("tag", false)));
|
||||
|
||||
final LinkedHashMap<NodeRef, Long> results = new LinkedHashMap<>();
|
||||
results.put(tagCoconut, 0L);
|
||||
results.put(tagBanana, 0L);
|
||||
results.put(tagApple, 0L);
|
||||
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(), eq(new Pair<>("tag", false)), any(), any())).willReturn(results);
|
||||
given(nodeServiceMock.getProperty(tagApple, ContentModel.PROP_NAME)).willReturn("apple");
|
||||
given(nodeServiceMock.getProperty(tagBanana, ContentModel.PROP_NAME)).willReturn("banana");
|
||||
given(nodeServiceMock.getProperty(tagCoconut, ContentModel.PROP_NAME)).willReturn("coconut");
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
final List<Tag> expectedTags = List.of(Tag.builder().tag("coconut").nodeRef(tagCoconut).create(),
|
||||
Tag.builder().tag("banana").nodeRef(tagBanana).create(),
|
||||
Tag.builder().tag("apple").nodeRef(tagApple).create());
|
||||
assertEquals(expectedTags, actualTags.getCollection());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTags_withEqualsClauseWhereQuery()
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag=expectedName)"));
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(PagingRequest.class), any(), any())).willReturn(pagingResultsMock);
|
||||
given(pagingResultsMock.getTotalResultCount()).willReturn(new Pair<>(Integer.MAX_VALUE, 0));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(PagingRequest.class), eq(Set.of("expectedname")), isNull());
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), eq(new ArrayList<>()), any(), eq(Set.of("expectedname")), isNull());
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualTags).isNotNull();
|
||||
}
|
||||
@@ -198,13 +329,13 @@ public class TagsImplTest
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag IN (expectedName1, expectedName2))"));
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(PagingRequest.class), any(), any())).willReturn(pagingResultsMock);
|
||||
given(pagingResultsMock.getTotalResultCount()).willReturn(new Pair<>(Integer.MAX_VALUE, 0));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(PagingRequest.class), eq(Set.of("expectedname1", "expectedname2")), isNull());
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE),any(), any(), eq(Set.of("expectedname1", "expectedname2")), isNull());
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualTags).isNotNull();
|
||||
}
|
||||
@@ -214,13 +345,13 @@ public class TagsImplTest
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag MATCHES ('expectedName*'))"));
|
||||
given(taggingServiceMock.getTags(any(StoreRef.class), any(PagingRequest.class), any(), any())).willReturn(pagingResultsMock);
|
||||
given(pagingResultsMock.getTotalResultCount()).willReturn(new Pair<>(Integer.MAX_VALUE, 0));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
given(parametersMock.getInclude()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final CollectionWithPagingInfo<Tag> actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock);
|
||||
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(PagingRequest.class), isNull(), eq(Set.of("expectedname*")));
|
||||
then(taggingServiceMock).should().getTags(eq(STORE_REF_WORKSPACE_SPACESSTORE), any(), any(), isNull(), eq(Set.of("expectedname*")));
|
||||
then(taggingServiceMock).shouldHaveNoMoreInteractions();
|
||||
assertThat(actualTags).isNotNull();
|
||||
}
|
||||
@@ -230,6 +361,7 @@ public class TagsImplTest
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag=expectedName AND tag IN (expectedName1, expectedName2))"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock));
|
||||
@@ -243,6 +375,7 @@ public class TagsImplTest
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(tag BETWEEN ('expectedName', 'expectedName2'))"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock));
|
||||
@@ -256,6 +389,7 @@ public class TagsImplTest
|
||||
{
|
||||
given(parametersMock.getPaging()).willReturn(pagingMock);
|
||||
given(parametersMock.getQuery()).willReturn(queryExtractor.getWhereClause("(NOT tag=expectedName)"));
|
||||
given(parametersMock.getSorting()).willReturn(new ArrayList<>());
|
||||
|
||||
//when
|
||||
final Throwable actualException = catchThrowable(() -> objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock));
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.alfresco</groupId>
|
||||
<artifactId>alfresco-community-repo</artifactId>
|
||||
<version>20.146</version>
|
||||
<version>20.155</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -23,225 +23,225 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.jscript;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Support class for finding categories, finding root nodes for categories and creating root categories.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public final class Classification extends BaseScopableProcessorExtension
|
||||
{
|
||||
private ServiceRegistry services;
|
||||
|
||||
private StoreRef storeRef;
|
||||
|
||||
/**
|
||||
* Set the default store reference
|
||||
*
|
||||
* @param storeRef the default store reference
|
||||
*/
|
||||
public void setStoreUrl(String storeRef)
|
||||
{
|
||||
this.storeRef = new StoreRef(storeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the service registry
|
||||
*
|
||||
* @param services the service registry
|
||||
*/
|
||||
public void setServiceRegistry(ServiceRegistry services)
|
||||
{
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the category nodes in a given classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getAllCategoryNodes(String aspect)
|
||||
{
|
||||
Object[] cats = buildCategoryNodes(services.getCategoryService().getCategories(
|
||||
storeRef, createQName(aspect), CategoryService.Depth.ANY));
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the aspects that define a classification.
|
||||
*
|
||||
* @return String[]
|
||||
*/
|
||||
public String[] getAllClassificationAspects()
|
||||
{
|
||||
Collection<QName> aspects = services.getCategoryService().getClassificationAspects();
|
||||
String[] answer = new String[aspects.size()];
|
||||
int i = 0;
|
||||
for (QName qname : aspects)
|
||||
{
|
||||
answer[i++] = qname.toPrefixString(this.services.getNamespaceService());
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a root category in a classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @param name String
|
||||
*/
|
||||
public CategoryNode createRootCategory(String aspect, String name)
|
||||
{
|
||||
NodeRef categoryNodeRef = services.getCategoryService().createRootCategory(storeRef, createQName(aspect), name);
|
||||
CategoryNode categoryNode = new CategoryNode(categoryNodeRef, this.services, getScope());
|
||||
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category node from the category node reference.
|
||||
*
|
||||
* @param categoryRef category node reference
|
||||
* @return {@link CategoryNode} category node
|
||||
*/
|
||||
public CategoryNode getCategory(String categoryRef)
|
||||
{
|
||||
CategoryNode result = null;
|
||||
NodeRef categoryNodeRef = new NodeRef(categoryRef);
|
||||
if (services.getNodeService().exists(categoryNodeRef) == true &&
|
||||
services.getDictionaryService().isSubClass(ContentModel.TYPE_CATEGORY, services.getNodeService().getType(categoryNodeRef)) == true)
|
||||
{
|
||||
result = new CategoryNode(categoryNodeRef, this.services, getScope());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root categories in a classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getRootCategories(String aspect)
|
||||
{
|
||||
Object[] cats = buildCategoryNodes(services.getCategoryService().getRootCategories(
|
||||
storeRef, createQName(aspect)));
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ordered, filtered and paged root categories in a classification.
|
||||
*
|
||||
* @param aspect
|
||||
* @param filter
|
||||
* @param maxItems
|
||||
* @param skipCount (offset)
|
||||
* @return
|
||||
*/
|
||||
public Scriptable getRootCategories(String aspect, String filter, int maxItems, int skipCount)
|
||||
{
|
||||
PagingRequest pagingRequest = new PagingRequest(skipCount, maxItems);
|
||||
List<ChildAssociationRef> rootCategories = services.getCategoryService().getRootCategories(storeRef, createQName(aspect), pagingRequest, true, filter).getPage();
|
||||
Object[] cats = buildCategoryNodes(rootCategories);
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category usage count.
|
||||
*
|
||||
* @param aspect String
|
||||
* @param maxCount int
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getCategoryUsage(String aspect, int maxCount)
|
||||
{
|
||||
List<Pair<NodeRef, Integer>> topCats = services.getCategoryService().getTopCategories(storeRef, createQName(aspect), maxCount);
|
||||
Object[] tags = new Object[topCats.size()];
|
||||
int i = 0;
|
||||
for (Pair<NodeRef, Integer> topCat : topCats)
|
||||
{
|
||||
tags[i++] = new Tag(new CategoryNode(topCat.getFirst(), this.services, getScope()), topCat.getSecond());
|
||||
}
|
||||
|
||||
return Context.getCurrentContext().newArray(getScope(), tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build category nodes.
|
||||
*
|
||||
* @param cars list of associations to category nodes
|
||||
* @return {@link Object}[] array of category nodes
|
||||
*/
|
||||
private Object[] buildCategoryNodes(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
Object[] categoryNodes = new Object[cars.size()];
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
categoryNodes[i++] = new CategoryNode(car.getChildRef(), this.services, getScope());
|
||||
}
|
||||
return categoryNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create QName from string
|
||||
*
|
||||
* @param s QName string value
|
||||
* @return {@link QName} qualified name object
|
||||
*/
|
||||
private QName createQName(String s)
|
||||
{
|
||||
QName qname;
|
||||
if (s.indexOf(QName.NAMESPACE_BEGIN) != -1)
|
||||
{
|
||||
qname = QName.createQName(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
qname = QName.createQName(s, this.services.getNamespaceService());
|
||||
}
|
||||
return qname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag class returned from getCategoryUsage().
|
||||
*/
|
||||
public final class Tag
|
||||
{
|
||||
private CategoryNode categoryNode;
|
||||
private int frequency = 0;
|
||||
|
||||
public Tag(CategoryNode categoryNode, int frequency)
|
||||
{
|
||||
this.categoryNode = categoryNode;
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
public CategoryNode getCategory()
|
||||
{
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
public int getFrequency()
|
||||
{
|
||||
return frequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.alfresco.repo.jscript;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Support class for finding categories, finding root nodes for categories and creating root categories.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public final class Classification extends BaseScopableProcessorExtension
|
||||
{
|
||||
private ServiceRegistry services;
|
||||
|
||||
private StoreRef storeRef;
|
||||
|
||||
/**
|
||||
* Set the default store reference
|
||||
*
|
||||
* @param storeRef the default store reference
|
||||
*/
|
||||
public void setStoreUrl(String storeRef)
|
||||
{
|
||||
this.storeRef = new StoreRef(storeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the service registry
|
||||
*
|
||||
* @param services the service registry
|
||||
*/
|
||||
public void setServiceRegistry(ServiceRegistry services)
|
||||
{
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the category nodes in a given classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getAllCategoryNodes(String aspect)
|
||||
{
|
||||
Object[] cats = buildCategoryNodes(services.getCategoryService().getCategories(
|
||||
storeRef, createQName(aspect), CategoryService.Depth.ANY));
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the aspects that define a classification.
|
||||
*
|
||||
* @return String[]
|
||||
*/
|
||||
public String[] getAllClassificationAspects()
|
||||
{
|
||||
Collection<QName> aspects = services.getCategoryService().getClassificationAspects();
|
||||
String[] answer = new String[aspects.size()];
|
||||
int i = 0;
|
||||
for (QName qname : aspects)
|
||||
{
|
||||
answer[i++] = qname.toPrefixString(this.services.getNamespaceService());
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a root category in a classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @param name String
|
||||
*/
|
||||
public CategoryNode createRootCategory(String aspect, String name)
|
||||
{
|
||||
NodeRef categoryNodeRef = services.getCategoryService().createRootCategory(storeRef, createQName(aspect), name);
|
||||
CategoryNode categoryNode = new CategoryNode(categoryNodeRef, this.services, getScope());
|
||||
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category node from the category node reference.
|
||||
*
|
||||
* @param categoryRef category node reference
|
||||
* @return {@link CategoryNode} category node
|
||||
*/
|
||||
public CategoryNode getCategory(String categoryRef)
|
||||
{
|
||||
CategoryNode result = null;
|
||||
NodeRef categoryNodeRef = new NodeRef(categoryRef);
|
||||
if (services.getNodeService().exists(categoryNodeRef) == true &&
|
||||
services.getDictionaryService().isSubClass(ContentModel.TYPE_CATEGORY, services.getNodeService().getType(categoryNodeRef)) == true)
|
||||
{
|
||||
result = new CategoryNode(categoryNodeRef, this.services, getScope());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root categories in a classification.
|
||||
*
|
||||
* @param aspect String
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getRootCategories(String aspect)
|
||||
{
|
||||
Object[] cats = buildCategoryNodes(services.getCategoryService().getRootCategories(
|
||||
storeRef, createQName(aspect)));
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ordered, filtered and paged root categories in a classification.
|
||||
*
|
||||
* @param aspect
|
||||
* @param filter
|
||||
* @param maxItems
|
||||
* @param skipCount (offset)
|
||||
* @return
|
||||
*/
|
||||
public Scriptable getRootCategories(String aspect, String filter, int maxItems, int skipCount)
|
||||
{
|
||||
PagingRequest pagingRequest = new PagingRequest(skipCount, maxItems);
|
||||
List<ChildAssociationRef> rootCategories = services.getCategoryService().getRootCategories(storeRef, createQName(aspect), pagingRequest, true, filter).getPage();
|
||||
Object[] cats = buildCategoryNodes(rootCategories);
|
||||
return Context.getCurrentContext().newArray(getScope(), cats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the category usage count.
|
||||
*
|
||||
* @param aspect String
|
||||
* @param maxCount int
|
||||
* @return Scriptable
|
||||
*/
|
||||
public Scriptable getCategoryUsage(String aspect, int maxCount)
|
||||
{
|
||||
List<Pair<NodeRef, Integer>> topCats = services.getCategoryService().getTopCategories(storeRef, createQName(aspect), maxCount);
|
||||
Object[] tags = new Object[topCats.size()];
|
||||
int i = 0;
|
||||
for (Pair<NodeRef, Integer> topCat : topCats)
|
||||
{
|
||||
tags[i++] = new Tag(new CategoryNode(topCat.getFirst(), this.services, getScope()), topCat.getSecond());
|
||||
}
|
||||
|
||||
return Context.getCurrentContext().newArray(getScope(), tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build category nodes.
|
||||
*
|
||||
* @param cars list of associations to category nodes
|
||||
* @return {@link Object}[] array of category nodes
|
||||
*/
|
||||
private Object[] buildCategoryNodes(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
Object[] categoryNodes = new Object[cars.size()];
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
categoryNodes[i++] = new CategoryNode(car.getChildRef(), this.services, getScope());
|
||||
}
|
||||
return categoryNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create QName from string
|
||||
*
|
||||
* @param s QName string value
|
||||
* @return {@link QName} qualified name object
|
||||
*/
|
||||
private QName createQName(String s)
|
||||
{
|
||||
QName qname;
|
||||
if (s.indexOf(QName.NAMESPACE_BEGIN) != -1)
|
||||
{
|
||||
qname = QName.createQName(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
qname = QName.createQName(s, this.services.getNamespaceService());
|
||||
}
|
||||
return qname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag class returned from getCategoryUsage().
|
||||
*/
|
||||
public final class Tag
|
||||
{
|
||||
private CategoryNode categoryNode;
|
||||
private int frequency = 0;
|
||||
|
||||
public Tag(CategoryNode categoryNode, int frequency)
|
||||
{
|
||||
this.categoryNode = categoryNode;
|
||||
this.frequency = frequency;
|
||||
}
|
||||
|
||||
public CategoryNode getCategory()
|
||||
{
|
||||
return categoryNode;
|
||||
}
|
||||
|
||||
public int getFrequency()
|
||||
{
|
||||
return frequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -414,34 +414,7 @@ public abstract class AbstractCategoryServiceImpl implements CategoryService
|
||||
int count = 0;
|
||||
boolean moreItems = false;
|
||||
|
||||
final Function<NodeRef, Collection<ChildAssociationRef>> childNodesSupplier = (nodeRef) -> {
|
||||
final Set<ChildAssociationRef> childNodes = new HashSet<>();
|
||||
if (CollectionUtils.isEmpty(exactNamesFilter) && CollectionUtils.isEmpty(alikeNamesFilter))
|
||||
{
|
||||
// lookup in DB without filtering
|
||||
childNodes.addAll(nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_SUBCATEGORIES, RegexQNamePattern.MATCH_ALL));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CollectionUtils.isNotEmpty(exactNamesFilter))
|
||||
{
|
||||
// lookup in DB filtering by name
|
||||
childNodes.addAll(nodeService.getChildrenByName(nodeRef, ContentModel.ASSOC_SUBCATEGORIES, exactNamesFilter));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(alikeNamesFilter))
|
||||
{
|
||||
// lookup using search engin filtering by name
|
||||
childNodes.addAll(getChildren(nodeRef, Mode.SUB_CATEGORIES, Depth.IMMEDIATE, sortByName, alikeNamesFilter, skipCount + maxItems + 1));
|
||||
}
|
||||
}
|
||||
|
||||
Stream<ChildAssociationRef> childNodesStream = childNodes.stream();
|
||||
if (sortByName)
|
||||
{
|
||||
childNodesStream = childNodesStream.sorted(Comparator.comparing(tag -> tag.getQName().getLocalName()));
|
||||
}
|
||||
return childNodesStream.collect(Collectors.toList());
|
||||
};
|
||||
final Function<NodeRef, Collection<ChildAssociationRef>> childNodesSupplier = getNodeRefCollectionFunction(sortByName, exactNamesFilter, alikeNamesFilter, skipCount, maxItems);
|
||||
|
||||
OUTER_LOOP: for(NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
@@ -468,6 +441,55 @@ public abstract class AbstractCategoryServiceImpl implements CategoryService
|
||||
return new ListBackedPagingResults<>(associations, moreItems);
|
||||
}
|
||||
|
||||
public Collection<ChildAssociationRef> getRootCategories(StoreRef storeRef, QName aspectName, Collection<String> exactNamesFilter, Collection<String> alikeNamesFilter)
|
||||
{
|
||||
final Set<NodeRef> nodeRefs = getClassificationNodes(storeRef, aspectName);
|
||||
final List<ChildAssociationRef> associations = new LinkedList<>();
|
||||
|
||||
final Function<NodeRef, Collection<ChildAssociationRef>> childNodesSupplier = getNodeRefCollectionFunction(false, exactNamesFilter, alikeNamesFilter, 0, 10000);
|
||||
|
||||
for (NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
Collection<ChildAssociationRef> children = childNodesSupplier.apply(nodeRef);
|
||||
associations.addAll(children);
|
||||
}
|
||||
|
||||
return associations;
|
||||
}
|
||||
|
||||
private Function<NodeRef, Collection<ChildAssociationRef>> getNodeRefCollectionFunction(boolean sortByName, Collection<String> exactNamesFilter, Collection<String> alikeNamesFilter, int skipCount, int maxItems)
|
||||
{
|
||||
final Function<NodeRef, Collection<ChildAssociationRef>> childNodesSupplier = (nodeRef) -> {
|
||||
final Set<ChildAssociationRef> childNodes = new HashSet<>();
|
||||
if (CollectionUtils.isEmpty(exactNamesFilter) && CollectionUtils.isEmpty(alikeNamesFilter))
|
||||
{
|
||||
// lookup in DB without filtering
|
||||
childNodes.addAll(nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_SUBCATEGORIES, RegexQNamePattern.MATCH_ALL));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CollectionUtils.isNotEmpty(exactNamesFilter))
|
||||
{
|
||||
// lookup in DB filtering by name
|
||||
childNodes.addAll(nodeService.getChildrenByName(nodeRef, ContentModel.ASSOC_SUBCATEGORIES, exactNamesFilter));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(alikeNamesFilter))
|
||||
{
|
||||
// lookup using search engine filtering by name
|
||||
childNodes.addAll(getChildren(nodeRef, Mode.SUB_CATEGORIES, Depth.IMMEDIATE, sortByName, alikeNamesFilter, skipCount + maxItems + 1));
|
||||
}
|
||||
}
|
||||
|
||||
Stream<ChildAssociationRef> childNodesStream = childNodes.stream();
|
||||
if (sortByName)
|
||||
{
|
||||
childNodesStream = childNodesStream.sorted(Comparator.comparing(tag -> tag.getQName().getLocalName()));
|
||||
}
|
||||
return childNodesStream.collect(Collectors.toList());
|
||||
};
|
||||
return childNodesSupplier;
|
||||
}
|
||||
|
||||
public Collection<ChildAssociationRef> getRootCategories(StoreRef storeRef, QName aspectName)
|
||||
{
|
||||
return getRootCategories(storeRef, aspectName, null);
|
||||
|
@@ -357,8 +357,13 @@ public class IdentityServiceFacadeFactoryBean implements FactoryBean<IdentitySer
|
||||
|
||||
private ClientRegistration.Builder createBuilder(OIDCProviderMetadata metadata)
|
||||
{
|
||||
final String authUri = Optional.of(metadata)
|
||||
.map(OIDCProviderMetadata::getAuthorizationEndpointURI)
|
||||
.map(URI::toASCIIString)
|
||||
.orElse(null);
|
||||
return ClientRegistration
|
||||
.withRegistrationId("ids")
|
||||
.authorizationUri(authUri)
|
||||
.tokenUri(metadata.getTokenEndpointURI().toASCIIString())
|
||||
.jwkSetUri(metadata.getJWKSetURI().toASCIIString())
|
||||
.issuerUri(config.getIssuerUrl())
|
||||
|
@@ -46,12 +46,16 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.EmptyPagingResults;
|
||||
@@ -61,6 +65,7 @@ import org.alfresco.repo.audit.AuditComponent;
|
||||
import org.alfresco.repo.coci.CheckOutCheckInServicePolicies.OnCheckOut;
|
||||
import org.alfresco.repo.copy.CopyServicePolicies.BeforeCopyPolicy;
|
||||
import org.alfresco.repo.copy.CopyServicePolicies.OnCopyCompletePolicy;
|
||||
import org.alfresco.repo.domain.query.QueryException;
|
||||
import org.alfresco.repo.event2.EventGenerator;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy;
|
||||
@@ -121,7 +126,7 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
|
||||
private static Log logger = LogFactory.getLog(TaggingServiceImpl.class);
|
||||
|
||||
private static Collator collator = Collator.getInstance();
|
||||
private static Collator collator = Collator.getInstance();
|
||||
|
||||
private NodeService nodeService;
|
||||
private NodeService nodeServiceInternal;
|
||||
@@ -138,6 +143,9 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
private static final String TAG_DETAILS_DELIMITER = "|";
|
||||
/** Next tag delimiter */
|
||||
private static final String NEXT_TAG_DELIMITER = "\n";
|
||||
/** Parameters Include count */
|
||||
private static final String PARAM_INCLUDE_COUNT = "count";
|
||||
|
||||
|
||||
private static Set<String> FORBIDDEN_TAGS_SEQUENCES = new HashSet<String>(Arrays.asList(new String[] {NEXT_TAG_DELIMITER, TAG_DETAILS_DELIMITER}));
|
||||
|
||||
@@ -494,8 +502,8 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
{
|
||||
// Lower the case of the tag
|
||||
tag = tag.toLowerCase();
|
||||
|
||||
return getTagNodeRef(storeRef, tag, true);
|
||||
|
||||
return getTagNodeRef(storeRef, tag, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -524,33 +532,33 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
|
||||
public NodeRef changeTag(StoreRef storeRef, String existingTag, String newTag)
|
||||
{
|
||||
if (existingTag == null)
|
||||
{
|
||||
throw new TaggingException("Existing tag cannot be null");
|
||||
}
|
||||
|
||||
if (newTag == null || StringUtils.isBlank(newTag))
|
||||
{
|
||||
throw new TaggingException("New tag cannot be blank");
|
||||
}
|
||||
if (existingTag == null)
|
||||
{
|
||||
throw new TaggingException("Existing tag cannot be null");
|
||||
}
|
||||
|
||||
existingTag = existingTag.toLowerCase();
|
||||
newTag = newTag.toLowerCase();
|
||||
if (newTag == null || StringUtils.isBlank(newTag))
|
||||
{
|
||||
throw new TaggingException("New tag cannot be blank");
|
||||
}
|
||||
|
||||
if (existingTag.equals(newTag))
|
||||
{
|
||||
throw new TaggingException("New and existing tags are the same");
|
||||
}
|
||||
|
||||
if (getTagNodeRef(storeRef, existingTag) == null)
|
||||
{
|
||||
throw new NonExistentTagException("Tag " + existingTag + " not found");
|
||||
}
|
||||
|
||||
if (getTagNodeRef(storeRef, newTag) != null)
|
||||
{
|
||||
throw new TagExistsException("Tag " + newTag + " already exists");
|
||||
}
|
||||
existingTag = existingTag.toLowerCase();
|
||||
newTag = newTag.toLowerCase();
|
||||
|
||||
if (existingTag.equals(newTag))
|
||||
{
|
||||
throw new TaggingException("New and existing tags are the same");
|
||||
}
|
||||
|
||||
if (getTagNodeRef(storeRef, existingTag) == null)
|
||||
{
|
||||
throw new NonExistentTagException("Tag " + existingTag + " not found");
|
||||
}
|
||||
|
||||
if (getTagNodeRef(storeRef, newTag) != null)
|
||||
{
|
||||
throw new TagExistsException("Tag " + newTag + " already exists");
|
||||
}
|
||||
|
||||
NodeRef tagNodeRef = getTagNodeRef(storeRef, existingTag);
|
||||
nodeService.setProperty(tagNodeRef, PROP_NAME, newTag);
|
||||
@@ -680,6 +688,21 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Long> calculateCount(StoreRef storeRef)
|
||||
{
|
||||
List<Pair<String, Integer>> tagsByCount = findTaggedNodesAndCountByTagName(storeRef);
|
||||
Map<String, Long> tagsByCountMap = new HashMap<>();
|
||||
if (tagsByCount != null)
|
||||
{
|
||||
for (Pair<String, Integer> tagByCountElem : tagsByCount)
|
||||
{
|
||||
tagsByCountMap.put(tagByCountElem.getFirst(), Long.valueOf(tagByCountElem.getSecond()));
|
||||
}
|
||||
}
|
||||
return tagsByCountMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see TaggingService#hasTag(NodeRef, String)
|
||||
*/
|
||||
@@ -695,12 +718,12 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
@SuppressWarnings("unchecked")
|
||||
public NodeRef addTag(final NodeRef nodeRef, final String tagName)
|
||||
{
|
||||
NodeRef newTagNodeRef = null;
|
||||
|
||||
if(tagName == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Must provide a non-null tag");
|
||||
}
|
||||
NodeRef newTagNodeRef = null;
|
||||
|
||||
if(tagName == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Must provide a non-null tag");
|
||||
}
|
||||
|
||||
updateTagBehaviour.disable();
|
||||
createTagBehaviour.disable();
|
||||
@@ -750,7 +773,7 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
*/
|
||||
public List<Pair<String, NodeRef>> addTags(NodeRef nodeRef, List<String> tags)
|
||||
{
|
||||
List<Pair<String, NodeRef>> ret = new ArrayList<Pair<String, NodeRef>>();
|
||||
List<Pair<String, NodeRef>> ret = new ArrayList<Pair<String, NodeRef>>();
|
||||
for (String tag : tags)
|
||||
{
|
||||
NodeRef tagNodeRef = addTag(nodeRef, tag);
|
||||
@@ -871,36 +894,36 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
int skipCount = pagingRequest.getSkipCount();
|
||||
int maxItems = pagingRequest.getMaxItems();
|
||||
int end = maxItems == Integer.MAX_VALUE ? totalItems : skipCount + maxItems;
|
||||
int size = (maxItems == Integer.MAX_VALUE ? totalItems : maxItems);
|
||||
int size = (maxItems == Integer.MAX_VALUE ? totalItems : maxItems);
|
||||
|
||||
final List<Pair<NodeRef, String>> sortedTags = new ArrayList<Pair<NodeRef, String>>(size);
|
||||
// grab all tags and sort (assume fairly low number of tags)
|
||||
for(NodeRef tagNode : currentTagNodes)
|
||||
{
|
||||
// grab all tags and sort (assume fairly low number of tags)
|
||||
for(NodeRef tagNode : currentTagNodes)
|
||||
{
|
||||
String tag = (String)this.nodeService.getProperty(tagNode, PROP_NAME);
|
||||
sortedTags.add(new Pair<NodeRef, String>(tagNode, tag));
|
||||
}
|
||||
}
|
||||
Collections.sort(sortedTags, new Comparator<Pair<NodeRef, String>>()
|
||||
{
|
||||
@Override
|
||||
public int compare(Pair<NodeRef, String> o1, Pair<NodeRef, String> o2)
|
||||
{
|
||||
String tag1 = o1.getSecond();
|
||||
String tag2 = o2.getSecond();
|
||||
return collator.compare(tag1, tag2);
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public int compare(Pair<NodeRef, String> o1, Pair<NodeRef, String> o2)
|
||||
{
|
||||
String tag1 = o1.getSecond();
|
||||
String tag2 = o2.getSecond();
|
||||
return collator.compare(tag1, tag2);
|
||||
}
|
||||
});
|
||||
|
||||
final List<Pair<NodeRef, String>> result = new ArrayList<Pair<NodeRef, String>>(size);
|
||||
Iterator<Pair<NodeRef, String>> it = sortedTags.iterator();
|
||||
Iterator<Pair<NodeRef, String>> it = sortedTags.iterator();
|
||||
for(int count = 0; count < end && it.hasNext(); count++)
|
||||
{
|
||||
Pair<NodeRef, String> tagPair = it.next();
|
||||
Pair<NodeRef, String> tagPair = it.next();
|
||||
|
||||
if(count < skipCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(count < skipCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.add(tagPair);
|
||||
}
|
||||
@@ -909,30 +932,30 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
|
||||
return new PagingResults<Pair<NodeRef, String>>()
|
||||
{
|
||||
@Override
|
||||
public List<Pair<NodeRef, String>> getPage()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public List<Pair<NodeRef, String>> getPage()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreItems()
|
||||
{
|
||||
return hasMoreItems;
|
||||
}
|
||||
@Override
|
||||
public boolean hasMoreItems()
|
||||
{
|
||||
return hasMoreItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Integer, Integer> getTotalResultCount()
|
||||
{
|
||||
Integer total = Integer.valueOf(totalItems);
|
||||
return new Pair<Integer, Integer>(total, total);
|
||||
}
|
||||
@Override
|
||||
public Pair<Integer, Integer> getTotalResultCount()
|
||||
{
|
||||
Integer total = Integer.valueOf(totalItems);
|
||||
return new Pair<Integer, Integer>(total, total);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryExecutionId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public String getQueryExecutionId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -956,7 +979,83 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
exactNamesFilter, alikeNamesFilter);
|
||||
|
||||
return mapPagingResult(rootCategories,
|
||||
(childAssociation) -> new Pair<>(childAssociation.getChildRef(), childAssociation.getQName().getLocalName()));
|
||||
(childAssociation) -> new Pair<>(childAssociation.getChildRef(), childAssociation.getQName().getLocalName()));
|
||||
}
|
||||
|
||||
public Map<NodeRef, Long> getTags(StoreRef storeRef, List<String> parameterIncludes, Pair<String, Boolean> sorting, Collection<String> exactNamesFilter, Collection<String> alikeNamesFilter)
|
||||
{
|
||||
ParameterCheck.mandatory("storeRef", storeRef);
|
||||
Collection<ChildAssociationRef> rootCategories = categoryService.getRootCategories(storeRef, ContentModel.ASPECT_TAGGABLE, exactNamesFilter, alikeNamesFilter);
|
||||
|
||||
Map<String, Long> tagsMap = new TreeMap<>();
|
||||
for (ChildAssociationRef childAssociation : rootCategories)
|
||||
{
|
||||
tagsMap.put(childAssociation.getQName().getLocalName(), 0L);
|
||||
}
|
||||
|
||||
Map<String, Long> tagsByCountMap = new HashMap<>();
|
||||
|
||||
if(parameterIncludes.contains(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
tagsByCountMap = calculateCount(storeRef);
|
||||
|
||||
for (Map.Entry<String, Long> entry : tagsMap.entrySet()) {
|
||||
entry.setValue(Optional.ofNullable(tagsByCountMap.get(entry.getKey())).orElse(0L));
|
||||
}
|
||||
}
|
||||
|
||||
//check if we should sort results. Can only sort by one parameter, default order is ascending
|
||||
if (sorting != null)
|
||||
{
|
||||
if (sorting.getFirst().equals("tag"))
|
||||
{
|
||||
if (!sorting.getSecond())
|
||||
{
|
||||
Stream<Map.Entry<String,Long>> sortedTags =
|
||||
tagsMap.entrySet().stream()
|
||||
.sorted(Collections.reverseOrder(Map.Entry.comparingByKey()));
|
||||
tagsMap = sortedTags.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream<Map.Entry<String,Long>> sortedTags =
|
||||
tagsMap.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByKey());
|
||||
tagsMap = sortedTags.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
|
||||
}
|
||||
}
|
||||
else if (sorting.getFirst().equals(PARAM_INCLUDE_COUNT))
|
||||
{
|
||||
if (tagsByCountMap.isEmpty())
|
||||
{
|
||||
throw new IllegalArgumentException("Tag count should be included when ordering by count");
|
||||
}
|
||||
|
||||
if (!sorting.getSecond())
|
||||
{
|
||||
Stream<Map.Entry<String, Long>> sortedTags =
|
||||
tagsMap.entrySet().stream()
|
||||
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
|
||||
tagsMap = sortedTags.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream<Map.Entry<String,Long>> sortedTags =
|
||||
tagsMap.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByValue());
|
||||
tagsMap = sortedTags.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<NodeRef, Long> tagNodeRefMap = new LinkedHashMap<>();
|
||||
|
||||
for (Map.Entry<String, Long> entry : tagsMap.entrySet())
|
||||
{
|
||||
tagNodeRefMap.put(getTagNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, entry.getKey()), entry.getValue());
|
||||
}
|
||||
|
||||
return tagNodeRefMap;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1190,15 +1289,15 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
*/
|
||||
private void getTagScopes(final NodeRef nodeRef, List<NodeRef> tagScopes, boolean firstOnly)
|
||||
{
|
||||
Boolean hasAspect = AuthenticationUtil.runAs(new RunAsWork<Boolean>()
|
||||
{
|
||||
@Override
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
return new Boolean(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TAGSCOPE));
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
Boolean hasAspect = AuthenticationUtil.runAs(new RunAsWork<Boolean>()
|
||||
{
|
||||
@Override
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
return new Boolean(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TAGSCOPE));
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
if (Boolean.TRUE.equals(hasAspect) == true)
|
||||
{
|
||||
tagScopes.add(nodeRef);
|
||||
@@ -1209,23 +1308,23 @@ public class TaggingServiceImpl implements TaggingService,
|
||||
}
|
||||
|
||||
NodeRef parent = AuthenticationUtil.runAs(new RunAsWork<NodeRef>()
|
||||
{
|
||||
@Override
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
NodeRef result = null;
|
||||
ChildAssociationRef assoc = nodeService.getPrimaryParent(nodeRef);
|
||||
if (assoc != null)
|
||||
{
|
||||
result = assoc.getParentRef();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
{
|
||||
@Override
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
NodeRef result = null;
|
||||
ChildAssociationRef assoc = nodeService.getPrimaryParent(nodeRef);
|
||||
if (assoc != null)
|
||||
{
|
||||
result = assoc.getParentRef();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
getTagScopes(parent, tagScopes, firstOnly);
|
||||
getTagScopes(parent, tagScopes, firstOnly);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,7 @@
|
||||
package org.alfresco.service.cmr.search;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -150,11 +151,21 @@ public interface CategoryService
|
||||
*/
|
||||
@Auditable(parameters = {"storeRef", "aspectName", "pagingRequest", "sortByName", "exactNamesFilter", "alikeNamesFilter"})
|
||||
default PagingResults<ChildAssociationRef> getRootCategories(StoreRef storeRef, QName aspectName, PagingRequest pagingRequest, boolean sortByName,
|
||||
Collection<String> exactNamesFilter, Collection<String> alikeNamesFilter)
|
||||
Collection<String> exactNamesFilter, Collection<String> alikeNamesFilter)
|
||||
{
|
||||
return new EmptyPagingResults<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of the root categories for an aspect/classification supporting multiple name filters.
|
||||
*/
|
||||
@Auditable(parameters = {"storeRef", "aspectName", "exactNamesFilter", "alikeNamesFilter"})
|
||||
default Collection<ChildAssociationRef> getRootCategories(StoreRef storeRef, QName aspectName, Collection<String> exactNamesFilter, Collection<String> alikeNamesFilter)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the root categories for an aspect/classification with names that start with filter
|
||||
*
|
||||
|
@@ -28,6 +28,7 @@ package org.alfresco.service.cmr.tagging;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.api.AlfrescoPublicApi;
|
||||
import org.alfresco.query.EmptyPagingResults;
|
||||
@@ -94,6 +95,18 @@ public interface TaggingService
|
||||
{
|
||||
return new EmptyPagingResults<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of tag NodeRefs and their respective usage count filtered by name and sorted by tag name or count
|
||||
*
|
||||
* @param storeRef
|
||||
* @param parameterIncludes
|
||||
* @param sorting
|
||||
* @param exactNamesFilter
|
||||
* @param alikeNamesFilter
|
||||
* @return
|
||||
*/
|
||||
Map<NodeRef, Long> getTags(StoreRef storeRef, List<String>parameterIncludes, Pair<String, Boolean> sorting, Collection<String> exactNamesFilter, Collection<String> alikeNamesFilter);
|
||||
|
||||
/**
|
||||
* Get all the tags currently available that match the provided filter.
|
||||
@@ -327,8 +340,7 @@ public interface TaggingService
|
||||
*/
|
||||
@NotAuditable
|
||||
Pair<List<String>, Integer> getPagedTags(StoreRef storeRef, String filter, int fromTag, int pageSize);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get tagged nodes and count of nodes group by tag name
|
||||
*
|
||||
@@ -362,6 +374,13 @@ public interface TaggingService
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param storeRef
|
||||
* @return a map with each tag name and its usage count
|
||||
*/
|
||||
Map<String, Long> calculateCount(StoreRef storeRef);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user