diff --git a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/tags/GetTagTests.java b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/tags/GetTagTests.java index 8890965195..769ff95b19 100644 --- a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/tags/GetTagTests.java +++ b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/tags/GetTagTests.java @@ -26,7 +26,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify admin user gets tag using REST API and status code is OK (200)") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) - public void adminIsAbleToGetTag() throws Exception + public void adminIsAbleToGetTag() { RestTagModel returnedTag = restClient.authenticateUser(adminUserModel).withCoreAPI().getTag(documentTag); restClient.assertStatusCodeIs(HttpStatus.OK); @@ -35,7 +35,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY, description = "Verify user with Manager role gets tag using REST API and status code is OK (200)") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY }) - public void userWithManagerRoleIsAbleToGetTag() throws Exception + public void userWithManagerRoleIsAbleToGetTag() { restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager)); @@ -47,7 +47,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Collaborator role gets tag using REST API and status code is OK (200)") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) - public void userWithCollaboratorRoleIsAbleToGetTag() throws Exception + public void userWithCollaboratorRoleIsAbleToGetTag() { restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteCollaborator)); RestTagModel returnedTag = restClient.withCoreAPI().getTag(documentTag); @@ -57,7 +57,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Contributor role gets tag using REST API and status code is OK (200)") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) - public void userWithContributorRoleIsAbleToGetTag() throws Exception + public void userWithContributorRoleIsAbleToGetTag() { restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteContributor)); RestTagModel returnedTag = restClient.withCoreAPI().getTag(documentTag); @@ -67,7 +67,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify user with Consumer role gets tag using REST API and status code is OK (200)") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) - public void userWithConsumerRoleIsAbleToGetTag() throws Exception + public void userWithConsumerRoleIsAbleToGetTag() { restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteConsumer)); RestTagModel returnedTag = restClient.withCoreAPI().getTag(documentTag); @@ -78,7 +78,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.SANITY, description = "Verify Manager user gets status code 401 if authentication call fails") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.SANITY }) // @Bug(id="MNT-16904", description = "It fails only on environment with tenants") - public void managerIsNotAbleToGetTagIfAuthenticationFails() throws Exception + public void managerIsNotAbleToGetTagIfAuthenticationFails() { UserModel managerUser = dataUser.usingAdmin().createRandomTestUser(); String managerPassword = managerUser.getPassword(); @@ -92,7 +92,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Verify that if tag id is invalid status code returned is 400") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) - public void invalidTagIdTest() throws Exception + public void invalidTagIdTest() { String tagId = documentTag.getId(); documentTag.setId("random_tag_value"); @@ -104,7 +104,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Check that properties filter is applied when getting tag using Manager user.") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) - public void checkPropertiesFilterIsApplied() throws Exception + public void checkPropertiesFilterIsApplied() { RestTagModel returnedTag = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager)) .withParams("properties=id,tag").withCoreAPI().getTag(documentTag); @@ -117,7 +117,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Check that Manager user can get tag of a folder.") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) - public void getTagOfAFolder() throws Exception + public void getTagOfAFolder() { RestTagModel returnedTag = restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager)) .withCoreAPI().getTag(folderTag); @@ -128,7 +128,7 @@ public class GetTagTests extends TagsDataPrep @TestRail(section = { TestGroup.REST_API, TestGroup.TAGS }, executionType = ExecutionType.REGRESSION, description = "Check default error model schema. Use invalid skipCount parameter.") @Test(groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) - public void checkDefaultErrorModelSchema() throws Exception + public void checkDefaultErrorModelSchema() { restClient.authenticateUser(usersWithRoles.getOneUserWithRole(UserRole.SiteManager)) .withParams("skipCount=abc").withCoreAPI().getTag(documentTag); @@ -140,13 +140,14 @@ public class GetTagTests extends TagsDataPrep } /** - * Verify that count field is not present for searched tag. + * Verify that count field is not present for searched tag when not requested. */ @Test(groups = {TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION}) public void testGetTag_notIncludingCount() { STEP("Create single tag as admin"); - final RestTagModel tagModel = createTagModelWithName(getRandomName(TAG_NAME_PREFIX).toLowerCase()); + String tagName = getRandomName(TAG_NAME_PREFIX).toLowerCase(); + final RestTagModel tagModel = createTagModelWithName(tagName); final RestTagModel createdTag = restClient.authenticateUser(adminUserModel).withCoreAPI().createSingleTag(tagModel); restClient.assertStatusCodeIs(CREATED); @@ -155,8 +156,26 @@ public class GetTagTests extends TagsDataPrep final RestTagModel searchedTag = restClient.withCoreAPI().getTag(createdTag); restClient.assertStatusCodeIs(OK); - searchedTag.assertThat().field(FIELD_TAG).is(tagModel.getTag()) - .assertThat().field(FIELD_ID).isNotEmpty() - .assertThat().field(FIELD_COUNT).isNull(); + RestTagModel expected = RestTagModel.builder().id(createdTag.getId()).tag(tagName).create(); + searchedTag.assertThat().isEqualTo(expected); + } + + /** + * Check that the count field can be included. + */ + @Test (groups = { TestGroup.REST_API, TestGroup.TAGS, TestGroup.REGRESSION }) + public void testGetTag_includeCount() + { + STEP("Create unused tag as admin"); + String tagName = getRandomName(TAG_NAME_PREFIX).toLowerCase(); + RestTagModel tagModel = createTagModelWithName(tagName); + RestTagModel createdTag = restClient.authenticateUser(adminUserModel).withCoreAPI().createSingleTag(tagModel); + + STEP("Get a single tag with the count field"); + RestTagModel searchedTag = restClient.withCoreAPI().include("count").getTag(createdTag); + + restClient.assertStatusCodeIs(OK); + RestTagModel expected = RestTagModel.builder().id(createdTag.getId()).tag(tagName).count(0).create(); + searchedTag.assertThat().isEqualTo(expected); } } diff --git a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/tags/UpdateTagTests.java b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/tags/UpdateTagTests.java index 3903a93d9c..b862f12401 100644 --- a/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/tags/UpdateTagTests.java +++ b/packaging/tests/tas-restapi/src/test/java/org/alfresco/rest/tags/UpdateTagTests.java @@ -305,7 +305,24 @@ public class UpdateTagTests extends TagsDataPrep returnedModel = restClient.authenticateUser(adminUserModel).withCoreAPI().usingTag(orphanTag).update(newTagName); restClient.assertStatusCodeIs(HttpStatus.OK); - returnedModel.assertThat().field("tag").is(newTagName); - returnedModel.assertThat().field("id").isNotNull(); + RestTagModel expected = RestTagModel.builder().id(orphanTag.getId()).tag(newTagName).create(); + returnedModel.assertThat().isEqualTo(expected); + } + + @Test (groups = { TestGroup.REST_API, TestGroup.TAGS }) + public void canUpdateTagAndGetCount() + { + STEP("Create an orphaned tag"); + String tagName = RandomData.getRandomName("tag").toLowerCase(); + RestTagModel createdTag = RestTagModel.builder().tag(tagName).create(); + RestTagModel tag = restClient.authenticateUser(adminUserModel).withCoreAPI().createSingleTag(createdTag); + + STEP("Update tag and request the count field"); + String newTagName = RandomData.getRandomName("new").toLowerCase(); + returnedModel = restClient.authenticateUser(adminUserModel).withCoreAPI().include("count").usingTag(tag).update(newTagName); + + restClient.assertStatusCodeIs(HttpStatus.OK); + RestTagModel expected = RestTagModel.builder().id(tag.getId()).tag(newTagName).count(0).create(); + returnedModel.assertThat().isEqualTo(expected); } } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/Tags.java b/remote-api/src/main/java/org/alfresco/rest/api/Tags.java index e75c1ef8ca..bb13199570 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/Tags.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/Tags.java @@ -38,10 +38,10 @@ import org.alfresco.service.cmr.repository.StoreRef; public interface Tags { List addTags(String nodeId, List tags, Parameters parameters); - Tag getTag(StoreRef storeRef, String tagId); + Tag getTag(StoreRef storeRef, String tagId, Parameters parameters); void deleteTag(String nodeId, String tagId); CollectionWithPagingInfo getTags(StoreRef storeRef, Parameters params); - Tag changeTag(StoreRef storeRef, String tagId, Tag tag); + Tag changeTag(StoreRef storeRef, String tagId, Tag tag, Parameters parameters); CollectionWithPagingInfo getTags(String nodeId, Parameters params); @Experimental diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/TagsImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/TagsImpl.java index 293507a7e3..49263d2af1 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/TagsImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/TagsImpl.java @@ -30,6 +30,7 @@ import static java.util.stream.Collectors.toList; import static org.alfresco.rest.antlr.WhereClauseParser.EQUALS; import static org.alfresco.rest.antlr.WhereClauseParser.IN; import static org.alfresco.rest.antlr.WhereClauseParser.MATCHES; +import static org.alfresco.service.cmr.repository.StoreRef.STORE_REF_WORKSPACE_SPACESSTORE; import static org.alfresco.service.cmr.tagging.TaggingService.TAG_ROOT_NODE_REF; import java.util.ArrayList; @@ -80,7 +81,7 @@ import org.apache.commons.collections.CollectionUtils; */ public class TagsImpl implements Tags { - private static final String PARAM_INCLUDE_COUNT = "count"; + 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"; @@ -129,12 +130,13 @@ public class TagsImpl implements Tags List> tagNodeRefs = taggingService.addTags(nodeRef, tagValues); List ret = new ArrayList<>(tags.size()); List> tagsCountPairList = taggingService.findTaggedNodesAndCountByTagName(nodeRef.getStoreRef()); - Map tagsCountMap = tagsCountPairList.stream().collect(Collectors.toMap(Pair::getFirst,Pair::getSecond)); + Map tagsCountMap = tagsCountPairList.stream().collect(Collectors.toMap(Pair::getFirst, pair -> Long.valueOf(pair.getSecond()))); for (Pair 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(0) + 1); + if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT)) + { + createdTag.setCount(Optional.ofNullable(tagsCountMap.get(createdTag.getTag())).orElse(0L) + 1); } ret.add(createdTag); } @@ -149,7 +151,7 @@ public class TagsImpl implements Tags public void deleteTag(String nodeId, String tagId) { NodeRef nodeRef = nodes.validateNode(nodeId); - getTag(tagId); + getTag(STORE_REF_WORKSPACE_SPACESSTORE, tagId, null); NodeRef existingTagNodeRef = validateTag(tagId); String tagValue = taggingService.getTagName(existingTagNodeRef); taggingService.removeTag(nodeRef, tagValue); @@ -182,15 +184,15 @@ public class TagsImpl implements Tags if (params.getInclude().contains(PARAM_INCLUDE_COUNT)) { List> tagsByCount = taggingService.findTaggedNodesAndCountByTagName(storeRef); - Map tagsByCountMap = new HashMap<>(); + Map tagsByCountMap = new HashMap<>(); if (tagsByCount != null) { for (Pair tagByCountElem : tagsByCount) { - tagsByCountMap.put(tagByCountElem.getFirst(), tagByCountElem.getSecond()); + tagsByCountMap.put(tagByCountElem.getFirst(), Long.valueOf(tagByCountElem.getSecond())); } } - tags.forEach(tag -> tag.setCount(Optional.ofNullable(tagsByCountMap.get(tag.getTag())).orElse(0))); + tags.forEach(tag -> tag.setCount(Optional.ofNullable(tagsByCountMap.get(tag.getTag())).orElse(0L))); } return CollectionWithPagingInfo.asPaged(paging, tags, results.hasMoreItems(), totalItems); @@ -208,15 +210,35 @@ public class TagsImpl implements Tags return checkTagRootAsNodePrimaryParent(tagId, tagNodeRef); } - public Tag changeTag(StoreRef storeRef, String tagId, Tag tag) + /** + * 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); - String newTagName = tag.getTag(); - NodeRef newTagNodeRef = taggingService.changeTag(storeRef, existingTagName, newTagName); - return new Tag(newTagNodeRef, newTagName); + 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) { @@ -232,18 +254,16 @@ public class TagsImpl implements Tags } } - public Tag getTag(String tagId) - { - return getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, tagId); - } - - public Tag getTag(StoreRef storeRef, String tagId) + @Override + public Tag getTag(StoreRef storeRef, String tagId, Parameters parameters) { NodeRef tagNodeRef = validateTag(storeRef, tagId); - String tagValue = taggingService.getTagName(tagNodeRef); - return new Tag(tagNodeRef, tagValue); + String tagName = taggingService.getTagName(tagNodeRef); + Long count = findCountIfRequested(storeRef, tagName, parameters); + return Tag.builder().nodeRef(tagNodeRef).tag(tagName).count(count).create(); } + @Override public CollectionWithPagingInfo getTags(String nodeId, Parameters params) { NodeRef nodeRef = nodes.validateOrLookupNode(nodeId); @@ -280,7 +300,7 @@ public class TagsImpl implements Tags .peek(tag -> { if (parameters.getInclude().contains(PARAM_INCLUDE_COUNT)) { - tag.setCount(0); + tag.setCount(0L); } }).collect(toList()); } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/Tag.java b/remote-api/src/main/java/org/alfresco/rest/api/model/Tag.java index dae4f92d97..94e1bf2757 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/Tag.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/Tag.java @@ -42,7 +42,7 @@ public class Tag implements Comparable { private NodeRef nodeRef; private String tag; - private Integer count; + private Long count; public Tag() { @@ -76,13 +76,13 @@ public class Tag implements Comparable this.tag = Optional.ofNullable(tag).map(String::toLowerCase).orElse(null); } - public Integer getCount() + public Long getCount() { return count; } - public void setCount(Integer count) + public void setCount(Long count) { this.count = count; } @@ -133,7 +133,7 @@ public class Tag implements Comparable { private NodeRef nodeRef; private String tag; - private Integer count; + private Long count; public Builder nodeRef(NodeRef nodeRef) { @@ -147,7 +147,7 @@ public class Tag implements Comparable return this; } - public Builder count(Integer count) + public Builder count(Long count) { this.count = count; return this; diff --git a/remote-api/src/main/java/org/alfresco/rest/api/tags/TagsEntityResource.java b/remote-api/src/main/java/org/alfresco/rest/api/tags/TagsEntityResource.java index abd53c3f0f..8b53398e43 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/tags/TagsEntityResource.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/tags/TagsEntityResource.java @@ -25,8 +25,8 @@ */ package org.alfresco.rest.api.tags; -import javax.servlet.http.HttpServletResponse; import java.util.List; +import javax.servlet.http.HttpServletResponse; import org.alfresco.rest.api.Tags; import org.alfresco.rest.api.model.Tag; @@ -73,13 +73,13 @@ public class TagsEntityResource implements EntityResourceAction.Read, @WebApiDescription(title="Updates a tag by unique Id") public Tag update(String id, Tag entity, Parameters parameters) { - return tags.changeTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id, entity); + return tags.changeTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id, entity, parameters); } @Override public Tag readById(String id, Parameters parameters) throws EntityNotFoundException { - return tags.getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id); + return tags.getTag(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, id, parameters); } /** diff --git a/remote-api/src/test/java/org/alfresco/rest/api/impl/TagsImplTest.java b/remote-api/src/test/java/org/alfresco/rest/api/impl/TagsImplTest.java index 2a7d9a9df3..e3b457a77b 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/impl/TagsImplTest.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/impl/TagsImplTest.java @@ -29,6 +29,7 @@ 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; @@ -115,6 +116,7 @@ public class TagsImplTest given(nodesMock.validateNode(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID)).willReturn(TAG_NODE_REF); given(taggingServiceMock.getTagName(TAG_NODE_REF)).willReturn(TAG_NAME); given(nodeServiceMock.getPrimaryParent(TAG_NODE_REF)).willReturn(primaryParentMock); + given(primaryParentMock.getParentRef()).willReturn(TAG_PARENT_NODE_REF); } @Test @@ -146,7 +148,7 @@ public class TagsImplTest then(taggingServiceMock).should().findTaggedNodesAndCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE); final List expectedTags = createTagsWithNodeRefs(List.of(TAG_NAME)).stream() - .peek(tag -> tag.setCount(0)) + .peek(tag -> tag.setCount(0L)) .collect(toList()); assertEquals(expectedTags, actualTags.getCollection()); } @@ -170,8 +172,8 @@ public class TagsImplTest final CollectionWithPagingInfo actualTags = objectUnderTest.getTags(STORE_REF_WORKSPACE_SPACESSTORE, parametersMock); then(taggingServiceMock).should().findTaggedNodesAndCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE); - final List expectedTags = List.of(Tag.builder().tag("taga").nodeRef(tagNodeA).count(5).create(), - Tag.builder().tag("tagb").nodeRef(tagNodeB).count(0).create()); + final List 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()); } @@ -266,7 +268,6 @@ public class TagsImplTest public void testDeleteTagById() { //when - given(primaryParentMock.getParentRef()).willReturn(TAG_PARENT_NODE_REF); objectUnderTest.deleteTagById(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID); then(authorityServiceMock).should().hasAdminAuthority(); @@ -425,7 +426,7 @@ public class TagsImplTest final List actualCreatedTags = objectUnderTest.createTags(tagsToCreate, parametersMock); final List expectedTags = createTagsWithNodeRefs(tagNames).stream() - .peek(tag -> tag.setCount(0)) + .peek(tag -> tag.setCount(0L)) .collect(toList()); assertThat(actualCreatedTags) .isNotNull() @@ -435,8 +436,8 @@ public class TagsImplTest @Test(expected = EntityNotFoundException.class) public void testGetTagByIdNotFoundValidation() { - given(primaryParentMock.getParentRef()).willReturn(TAG_NODE_REF); - objectUnderTest.getTag(STORE_REF_WORKSPACE_SPACESSTORE,TAG_ID); + given(nodesMock.validateNode(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID)).willThrow(EntityNotFoundException.class); + objectUnderTest.getTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, null); then(nodeServiceMock).shouldHaveNoInteractions(); then(nodesMock).should().validateNode(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID); then(nodesMock).shouldHaveNoMoreInteractions(); @@ -459,8 +460,8 @@ public class TagsImplTest List actual = objectUnderTest.addTags(CONTENT_NODE_ID, tags, parametersMock); - final List expected = List.of(Tag.builder().tag("taga").nodeRef(tagNodeA).count(5).create(), - Tag.builder().tag("tagb").nodeRef(tagNodeB).count(1).create()); + final List expected = List.of(Tag.builder().tag("taga").nodeRef(tagNodeA).count(5L).create(), + Tag.builder().tag("tagb").nodeRef(tagNodeB).count(1L).create()); assertEquals("Unexpected tags returned.", expected, actual); } @@ -508,6 +509,53 @@ public class TagsImplTest objectUnderTest.getTags(CONTENT_NODE_ID, parametersMock); } + @Test + public void testChangeTag() + { + Tag suppliedTag = Tag.builder().tag("new-name").create(); + given(taggingServiceMock.changeTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME, "new-name")).willReturn(TAG_NODE_REF); + + Tag tag = objectUnderTest.changeTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, suppliedTag, parametersMock); + + Tag expected = Tag.builder().nodeRef(TAG_NODE_REF).tag("new-name").create(); + assertEquals("Unexpected return value", expected, tag); + } + + @Test + public void testChangeTagAndGetCount() + { + Tag suppliedTag = Tag.builder().tag("new-name").create(); + given(taggingServiceMock.changeTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME, "new-name")).willReturn(TAG_NODE_REF); + given(parametersMock.getInclude()).willReturn(List.of(PARAM_INCLUDE_COUNT)); + given(taggingServiceMock.findCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME)).willReturn(3L); + + Tag tag = objectUnderTest.changeTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, suppliedTag, parametersMock); + + Tag expected = Tag.builder().nodeRef(TAG_NODE_REF).tag("new-name").count(3L).create(); + assertEquals("Unexpected return value", expected, tag); + } + + @Test + public void testGetTag() + { + Tag tag = objectUnderTest.getTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, parametersMock); + + Tag expected = Tag.builder().nodeRef(TAG_NODE_REF).tag(TAG_NAME).create(); + assertEquals("Unexpected tag returned", expected, tag); + } + + @Test + public void testGetTagWithCount() + { + given(parametersMock.getInclude()).willReturn(List.of(PARAM_INCLUDE_COUNT)); + given(taggingServiceMock.findCountByTagName(STORE_REF_WORKSPACE_SPACESSTORE, TAG_NAME)).willReturn(0L); + + Tag tag = objectUnderTest.getTag(STORE_REF_WORKSPACE_SPACESSTORE, TAG_ID, parametersMock); + + Tag expected = Tag.builder().nodeRef(TAG_NODE_REF).tag(TAG_NAME).count(0L).create(); + assertEquals("Unexpected tag returned", expected, tag); + } + private static List> createTagAndNodeRefPairs(final List tagNames) { return tagNames.stream() diff --git a/repository/src/main/java/org/alfresco/repo/tagging/TaggingServiceImpl.java b/repository/src/main/java/org/alfresco/repo/tagging/TaggingServiceImpl.java index f200a16d6e..e06c1b7cd7 100644 --- a/repository/src/main/java/org/alfresco/repo/tagging/TaggingServiceImpl.java +++ b/repository/src/main/java/org/alfresco/repo/tagging/TaggingServiceImpl.java @@ -27,8 +27,10 @@ package org.alfresco.repo.tagging; import static java.util.Collections.emptyMap; +import static org.alfresco.model.ContentModel.ASPECT_WORKING_COPY; import static org.alfresco.model.ContentModel.ASSOC_SUBCATEGORIES; import static org.alfresco.model.ContentModel.PROP_NAME; +import static org.alfresco.service.cmr.search.SearchService.LANGUAGE_LUCENE; import static org.alfresco.service.namespace.NamespaceService.CONTENT_MODEL_1_0_URI; import java.io.BufferedReader; @@ -333,7 +335,7 @@ public class TaggingServiceImpl implements TaggingService, public void beforeDeleteNode(NodeRef nodeRef) { if (this.nodeService.exists(nodeRef) == true && - this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TAGGABLE) == true && !this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_WORKING_COPY)) + this.nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TAGGABLE) == true && !this.nodeService.hasAspect(nodeRef, ASPECT_WORKING_COPY)) { updateAllScopeTags(nodeRef, Boolean.FALSE); } @@ -1241,7 +1243,7 @@ public class TaggingServiceImpl implements TaggingService, // Do the search for nodes resultSet = this.searchService.query( storeRef, - SearchService.LANGUAGE_LUCENE, + LANGUAGE_LUCENE, "+PATH:\"/cm:taggable/cm:" + ISO9075.encode(tag) + "/member\""); List nodeRefs = resultSet.getNodeRefs(); return nodeRefs; @@ -1270,7 +1272,7 @@ public class TaggingServiceImpl implements TaggingService, // Do query resultSet = this.searchService.query( storeRef, - SearchService.LANGUAGE_LUCENE, + LANGUAGE_LUCENE, "+PATH:\"" + pathString + "//*\" +PATH:\"/cm:taggable/cm:" + ISO9075.encode(tag) + "/member\""); List nodeRefs = resultSet.getNodeRefs(); return nodeRefs; @@ -1538,7 +1540,7 @@ public class TaggingServiceImpl implements TaggingService, public void afterCheckOut(NodeRef workingCopy) { if (this.nodeService.exists(workingCopy) == true && this.nodeService.hasAspect(workingCopy, ContentModel.ASPECT_TAGGABLE) == true - && this.nodeService.hasAspect(workingCopy, ContentModel.ASPECT_WORKING_COPY)) + && this.nodeService.hasAspect(workingCopy, ASPECT_WORKING_COPY)) { updateAllScopeTags(workingCopy, Boolean.FALSE); } @@ -1550,10 +1552,10 @@ public class TaggingServiceImpl implements TaggingService, @Override public List> findTaggedNodesAndCountByTagName(StoreRef storeRef) { - String queryTaggeble = "ASPECT:\"" + ContentModel.ASPECT_TAGGABLE + "\"" + "-ASPECT:\"" + ContentModel.ASPECT_WORKING_COPY + "\""; + String queryTaggeble = "ASPECT:\"" + ContentModel.ASPECT_TAGGABLE + "\"" + "-ASPECT:\"" + ASPECT_WORKING_COPY + "\""; SearchParameters sp = new SearchParameters(); sp.setQuery(queryTaggeble); - sp.setLanguage(SearchService.LANGUAGE_LUCENE); + sp.setLanguage(LANGUAGE_LUCENE); sp.addStore(storeRef); sp.addFieldFacet(new FieldFacet("TAG")); @@ -1573,6 +1575,32 @@ public class TaggingServiceImpl implements TaggingService, } } + /** {@inheritDoc} */ + @Override + public long findCountByTagName(StoreRef storeRef, String name) + { + String query = "TAG:\"" + name + "\"" + "-ASPECT:\"" + ASPECT_WORKING_COPY + "\""; + SearchParameters sp = new SearchParameters(); + sp.setQuery(query); + sp.setLanguage(LANGUAGE_LUCENE); + sp.addStore(storeRef); + + ResultSet resultSet = null; + try + { + // Do the search for nodes + resultSet = this.searchService.query(sp); + return resultSet.getNumberFound(); + } + finally + { + if (resultSet != null) + { + resultSet.close(); + } + } + } + @Experimental @Override public List> createTags(final StoreRef storeRef, final List tagNames) diff --git a/repository/src/main/java/org/alfresco/service/cmr/tagging/TaggingService.java b/repository/src/main/java/org/alfresco/service/cmr/tagging/TaggingService.java index e5023e2ab2..0c48c09817 100644 --- a/repository/src/main/java/org/alfresco/service/cmr/tagging/TaggingService.java +++ b/repository/src/main/java/org/alfresco/service/cmr/tagging/TaggingService.java @@ -338,6 +338,16 @@ public interface TaggingService @NotAuditable List> findTaggedNodesAndCountByTagName(StoreRef storeRef); + /** + * Get the number of tagged nodes for a given tag. + * + * @param storeRef The store containing the nodes. + * @param name The name of the tag. + * @return The number of nodes tagged with the specified tag. + */ + @NotAuditable + long findCountByTagName(StoreRef storeRef, String name); + /** * Creates orphan tags. Tag names case will be lowered. *