diff --git a/remote-api/src/main/java/org/alfresco/rest/api/SizeDetails.java b/remote-api/src/main/java/org/alfresco/rest/api/SizeDetails.java index d268b66f88..3412f27d65 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/SizeDetails.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/SizeDetails.java @@ -29,11 +29,12 @@ import org.alfresco.rest.api.model.NodeSizeDetails; public interface SizeDetails { - enum PROCESSINGSTATE - { - NOT_INITIATED, IN_PROGRESS, COMPLETED; - } + NodeSizeDetails generateNodeSizeDetailsRequest(String nodeId); - NodeSizeDetails generateNodeSizeDetailsRequest(String nodeId); - NodeSizeDetails getNodeSizeDetails(String nodeId, String jobId); + NodeSizeDetails getNodeSizeDetails(String nodeId, String jobId); + + enum ProcessingState + { + NOT_INITIATED, PENDING, IN_PROGRESS, COMPLETED + } } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/impl/SizeDetailsImpl.java b/remote-api/src/main/java/org/alfresco/rest/api/impl/SizeDetailsImpl.java index 5627ee62c2..966a9ec21f 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/impl/SizeDetailsImpl.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/impl/SizeDetailsImpl.java @@ -25,46 +25,34 @@ */ package org.alfresco.rest.api.impl; +import static org.alfresco.rest.api.SizeDetails.ProcessingState.COMPLETED; +import static org.alfresco.rest.api.SizeDetails.ProcessingState.IN_PROGRESS; +import static org.alfresco.rest.api.SizeDetails.ProcessingState.NOT_INITIATED; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.model.ContentModel; import org.alfresco.repo.action.executer.NodeSizeDetailActionExecutor; import org.alfresco.repo.cache.SimpleCache; -import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.SizeDetails; -import org.alfresco.rest.api.model.Node; -import org.alfresco.rest.api.model.NodePermissions; import org.alfresco.rest.api.model.NodeSizeDetails; import org.alfresco.rest.framework.core.exceptions.InvalidNodeTypeException; import org.alfresco.rest.framework.core.exceptions.UnprocessableContentException; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ActionService; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.PermissionService; -import org.alfresco.service.namespace.QName; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.alfresco.service.cmr.repository.NodeRef; -import java.io.Serializable; -import java.util.Map; -import java.util.HashMap; - -import static org.alfresco.rest.api.SizeDetails.PROCESSINGSTATE.COMPLETED; -import static org.alfresco.rest.api.SizeDetails.PROCESSINGSTATE.NOT_INITIATED; -import static org.alfresco.rest.api.SizeDetails.PROCESSINGSTATE.IN_PROGRESS; public class SizeDetailsImpl implements SizeDetails { - private static final Logger LOG = LoggerFactory.getLogger(SizeDetailsImpl.class); - private static final String STATUS = "status"; - private static final String ACTIONID = "actionId"; - private static final String INVALID_NODEID = "Invalid parameter: value of nodeId is invalid"; - private static final String INVALID_JOBID = "Invalid parameter: value of jobId is invalid"; - private static final String FOLDER = "folder"; + private static final String ACTION_ID = "actionId"; private Nodes nodes; - private NodeService nodeService; - private PermissionService permissionService; + private NodeRef nodeRef; private ActionService actionService; - private SimpleCache> simpleCache; + private SimpleCache> simpleCache; private int defaultItems; public void setNodes(Nodes nodes) @@ -72,16 +60,6 @@ public class SizeDetailsImpl implements SizeDetails this.nodes = nodes; } - public void setPermissionService(PermissionService permissionService) - { - this.permissionService = permissionService; - } - - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - public void setActionService(ActionService actionService) { this.actionService = actionService; @@ -103,16 +81,17 @@ public class SizeDetailsImpl implements SizeDetails @Override public NodeSizeDetails generateNodeSizeDetailsRequest(String nodeId) { - NodeRef nodeRef = nodes.validateNode(nodeId); + nodeRef = nodes.validateOrLookupNode(nodeId); validateType(nodeRef); String actionId; - if(simpleCache.get(nodeId) == null) + if (!simpleCache.contains(nodeId)) { - actionId = executeAction(nodeRef, defaultItems, simpleCache); - } else + actionId = executeAction(); + } + else { Map result = simpleCache.get(nodeRef.getId()); - actionId = (String)result.get(ACTIONID); + actionId = (String) result.get(ACTION_ID); } return new NodeSizeDetails(actionId); } @@ -123,29 +102,27 @@ public class SizeDetailsImpl implements SizeDetails @Override public NodeSizeDetails getNodeSizeDetails(final String nodeId, final String jobId) { - NodeRef nodeRef = nodes.validateNode(nodeId); + NodeRef nodeRef = nodes.validateOrLookupNode(nodeId); validateType(nodeRef); - if(simpleCache.get(nodeId) == null) + if (!simpleCache.contains(nodeId)) { return new NodeSizeDetails(nodeId, NOT_INITIATED.name()); } - LOG.debug("Executing executorResultToSizeDetail method"); return executorResultToSizeDetail(simpleCache.get(nodeId), nodeId, jobId); } /** * Executing Action Asynchronously. */ - private String executeAction(NodeRef nodeRef, int defaultItems, SimpleCache> simpleCache) + private String executeAction() { Map currentStatus = new HashMap<>(); - currentStatus.put(STATUS,IN_PROGRESS.name()); + currentStatus.put("status",IN_PROGRESS.name()); Action folderSizeAction = actionService.createAction(NodeSizeDetailActionExecutor.NAME); - currentStatus.put(ACTIONID,folderSizeAction.getId()); + currentStatus.put(ACTION_ID,folderSizeAction.getId()); folderSizeAction.setTrackStatus(true); - folderSizeAction.setExecuteAsynchronously(true); folderSizeAction.setParameterValue(NodeSizeDetailActionExecutor.DEFAULT_SIZE, defaultItems); simpleCache.put(nodeRef.getId(),currentStatus); actionService.executeAction(folderSizeAction, nodeRef, false, true); @@ -155,28 +132,24 @@ public class SizeDetailsImpl implements SizeDetails /** * Converting action executor response to their respective model class. */ - private NodeSizeDetails executorResultToSizeDetail(final Map result, String nodeId, String jobId) + private NodeSizeDetails executorResultToSizeDetail(final Map result, String nodeId, String jobId) { - if(result.containsKey(NodeSizeDetailActionExecutor.EXCEPTION)) + if (result.containsKey(NodeSizeDetailActionExecutor.EXCEPTION)) { return new NodeSizeDetails(nodeId, COMPLETED.name()); } - // Check for the presence of "size" key. - boolean hasSizeKey = result.containsKey("size"); - - if (hasSizeKey) + if (result.containsKey("size")) { - NodeSizeDetails nodeSizeDetails = new NodeSizeDetails((String) result.get("nodeId"), - (Long) result.get("size"), - (String) result.get("calculatedAt"), - (Integer) result.get("numberOfFiles"), - COMPLETED.name(), - (String) result.get(ACTIONID)); + NodeSizeDetails nodeSizeDetails = + new NodeSizeDetails((String) result.get("nodeId"), (Long) result.get("size"), + (Date) result.get("calculatedAt"), (Integer) result.get("numberOfFiles"), + COMPLETED.name(), (String) result.get(ACTION_ID)); - if(!nodeSizeDetails.getJobId().equalsIgnoreCase(jobId)) + if (!nodeSizeDetails.getJobId() + .equalsIgnoreCase(jobId)) { - throw new UnprocessableContentException(INVALID_JOBID); + throw new UnprocessableContentException("Invalid parameter: value of jobId is invalid"); } return nodeSizeDetails; } @@ -188,25 +161,9 @@ public class SizeDetailsImpl implements SizeDetails private void validateType(NodeRef nodeRef) throws InvalidNodeTypeException { - QName qName = nodeService.getType(nodeRef); - validatePermissions(nodeRef, nodeRef.getId()); - if(!FOLDER.equalsIgnoreCase(qName.getLocalName())) + if (!nodes.isSubClass(nodeRef, ContentModel.TYPE_FOLDER, false)) { - throw new InvalidNodeTypeException(INVALID_NODEID); - } - } - - /** - * Validating node permission [i.e. READ permission should be there ] - */ - private void validatePermissions(NodeRef nodeRef, String nodeId) - { - Node nodeInfo = nodes.getNode(nodeId); - NodePermissions nodePerms = nodeInfo.getPermissions(); - // Validate permissions. - if (nodePerms != null && permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED) - { - throw new AccessDeniedException("permissions.err_access_denied"); + throw new InvalidNodeTypeException("Invalid parameter: value of nodeId is invalid"); } } } \ No newline at end of file diff --git a/remote-api/src/main/java/org/alfresco/rest/api/model/NodeSizeDetails.java b/remote-api/src/main/java/org/alfresco/rest/api/model/NodeSizeDetails.java index c30a9dbbe4..b3c1a5bc43 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/model/NodeSizeDetails.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/model/NodeSizeDetails.java @@ -25,17 +25,17 @@ */ package org.alfresco.rest.api.model; -import org.json.simple.JSONObject; - +import java.util.Date; import java.util.Objects; +import org.json.simple.JSONObject; + public class NodeSizeDetails { - private String nodeId; - private Long size; - private String calculatedAt; + private String id; + private Long sizeInBytes; + private Date calculatedAt; private Integer numberOfFiles; - private String status; private String jobId; public NodeSizeDetails(String jobId) @@ -43,48 +43,62 @@ public class NodeSizeDetails this.jobId = jobId; } - public NodeSizeDetails(String nodeId, String status) + public NodeSizeDetails(String id, String currentStatus) { - this.nodeId = nodeId; - this.status = status; + this.id = id; + NodeSizeDetails.status.valueOf(currentStatus); } - public NodeSizeDetails(String nodeId, Long size, String calculatedAt, Integer numberOfFiles, String status, String jobId) + public NodeSizeDetails(String id, Long sizeInBytes, Date calculatedAt, Integer numberOfFiles, String currentStatus, + String jobId) { - this.nodeId = nodeId; - this.size = size; + this.id = id; + this.sizeInBytes = sizeInBytes; this.calculatedAt = calculatedAt; this.numberOfFiles = numberOfFiles; - this.status = status; + NodeSizeDetails.status.valueOf(currentStatus); this.jobId = jobId; } - public String getNodeId() + public static String parseJson(JSONObject jsonObject) { - return nodeId; + if (jsonObject == null) + { + return null; + } + + String jobId = (String) jsonObject.get("jobId"); + jobId = jobId.replace("<", "") + .replace(">", ""); + return jobId; } - public void setNodeId(String nodeId) + public String getId() { - this.nodeId = nodeId; + return id; } - public Long getSize() + public void setId(String id) { - return size; + this.id = id; } - public void setSize(Long size) + public Long getSizeInBytes() { - this.size = size; + return sizeInBytes; } - public String getCalculatedAt() + public void setSizeInBytes(Long sizeInBytes) + { + this.sizeInBytes = sizeInBytes; + } + + public Date getCalculatedAt() { return calculatedAt; } - public void setCalculatedAt(String calculatedAt) + public void setCalculatedAt(Date calculatedAt) { this.calculatedAt = calculatedAt; } @@ -99,16 +113,6 @@ public class NodeSizeDetails this.numberOfFiles = numberOfFiles; } - public String getStatus() - { - return status; - } - - public void setStatus(String status) - { - this.status = status; - } - public String getJobId() { return jobId; @@ -119,18 +123,6 @@ public class NodeSizeDetails this.jobId = jobId; } - public static String parseJson(JSONObject jsonObject) - { - if (jsonObject == null) - { - return null; - } - - String jobId = (String)jsonObject.get("jobId"); - jobId = jobId.replace("<", "").replace(">", ""); - return jobId; - } - @Override public boolean equals(Object o) { @@ -143,25 +135,27 @@ public class NodeSizeDetails return false; } NodeSizeDetails that = (NodeSizeDetails) o; - return Objects.equals(nodeId, that.nodeId) && Objects.equals(size, that.size) && Objects.equals(calculatedAt, that.calculatedAt) && Objects.equals(numberOfFiles, that.numberOfFiles) && Objects.equals(status, that.status) && Objects.equals(jobId, that.jobId); + return Objects.equals(id, that.id) && Objects.equals(sizeInBytes, that.sizeInBytes) && Objects.equals( + calculatedAt, that.calculatedAt) && Objects.equals(numberOfFiles, that.numberOfFiles) + && Objects.equals(jobId, that.jobId); } @Override public int hashCode() { - return Objects.hash(nodeId, size, calculatedAt, numberOfFiles, status, jobId); + return Objects.hash(id, sizeInBytes, calculatedAt, numberOfFiles, jobId); } @Override public String toString() { - return "NodeSizeDetails{" + - "nodeId='" + nodeId + '\'' + - ", size=" + size + - ", calculatedAt='" + calculatedAt + '\'' + - ", numberOfFiles=" + numberOfFiles + - ", status='" + status + '\'' + - ", jobId='" + jobId + '\'' + - '}'; + return "NodeSizeDetails{" + "id='" + id + '\'' + ", sizeInBytes=" + sizeInBytes + ", calculatedAt=" + + calculatedAt + ", numberOfFiles=" + numberOfFiles + ", jobId='" + jobId + '\'' + '}'; } + + private enum status + { + NOT_INITIATED, PENDING, IN_PROGRESS, COMPLETED + } + } diff --git a/remote-api/src/main/java/org/alfresco/rest/api/nodes/NodeSizeDetailsRelation.java b/remote-api/src/main/java/org/alfresco/rest/api/nodes/NodeSizeDetailsRelation.java index dfbbffc8a8..537c322fd7 100644 --- a/remote-api/src/main/java/org/alfresco/rest/api/nodes/NodeSizeDetailsRelation.java +++ b/remote-api/src/main/java/org/alfresco/rest/api/nodes/NodeSizeDetailsRelation.java @@ -26,6 +26,9 @@ package org.alfresco.rest.api.nodes; +import java.util.Collections; +import java.util.List; + import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.SizeDetails; import org.alfresco.rest.api.model.NodeSizeDetails; @@ -38,20 +41,14 @@ import org.alfresco.rest.framework.resource.RelationshipResource; import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.util.ParameterCheck; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.extensions.webscripts.Status; -import java.util.Arrays; -import java.util.List; @RelationshipResource(name = "size-details", entityResource = NodesEntityResource.class, title = "Node Size Details") -public class NodeSizeDetailsRelation implements - RelationshipResourceAction.ReadById, - RelationshipResourceAction.Create, - InitializingBean { +public class NodeSizeDetailsRelation implements RelationshipResourceAction.ReadById, + RelationshipResourceAction.Create, InitializingBean +{ - private static final Logger LOG = LoggerFactory.getLogger(NodeSizeDetailsRelation.class); private Nodes nodes; private SizeDetails sizeDetails; @@ -68,27 +65,27 @@ public class NodeSizeDetailsRelation implements @Override public void afterPropertiesSet() { - ParameterCheck.mandatory("nodes", this.nodes); + ParameterCheck.mandatory("sizeDetails", this.sizeDetails); } @WebApiDescription(title = "Create node-size details request", successStatus = Status.STATUS_ACCEPTED) - @WebApiParam(name="nodeSizeEntity", title="Node Size Details Request", description="Request for processing Node Size.", - kind= ResourceParameter.KIND.HTTP_BODY_OBJECT, allowMultiple=false) + @WebApiParam(name = "nodeSizeEntity", title = "Node Size Details Request", + description = "Request for processing Node Size.", kind = ResourceParameter.KIND.HTTP_BODY_OBJECT, + allowMultiple = false) @Override public List create(String nodeId, List nodeSizeEntity, Parameters parameters) { - LOG.debug(" Executing generateNodeSizeDetailsRequest method "); - return Arrays.asList(sizeDetails.generateNodeSizeDetailsRequest(nodeId)); + return List.of(sizeDetails.generateNodeSizeDetailsRequest(nodeId)); } @WebApiDescription(title = "Get Node Size Details", description = "Get the Node Size Details") - @WebApiParameters({ - @WebApiParam(name="nodeId", title="The unique id of the Node being addressed", description="A single node id"), - @WebApiParam(name="jobId", title="Job Id to get the NodeSizeDetails", description="JobId")}) + @WebApiParameters({ @WebApiParam(name = "nodeId", title = "The unique id of the Node being addressed", + description = "A single node id"), + @WebApiParam(name = "jobId", title = "Job Id to get the NodeSizeDetails", description = "JobId") }) @Override - public NodeSizeDetails readById(String nodeId, String jobId, Parameters parameters) throws RelationshipResourceNotFoundException + public NodeSizeDetails readById(String nodeId, String jobId, Parameters parameters) + throws RelationshipResourceNotFoundException { - LOG.debug(" Executing getNodeSizeDetails method "); - return sizeDetails.getNodeSizeDetails(nodeId,jobId); + return sizeDetails.getNodeSizeDetails(nodeId, jobId); } } diff --git a/remote-api/src/main/resources/alfresco/public-rest-context.xml b/remote-api/src/main/resources/alfresco/public-rest-context.xml index 4b9d7546a7..da717df745 100644 --- a/remote-api/src/main/resources/alfresco/public-rest-context.xml +++ b/remote-api/src/main/resources/alfresco/public-rest-context.xml @@ -998,8 +998,6 @@ - - diff --git a/remote-api/src/test/java/org/alfresco/rest/api/impl/SizeDetailsImplTest.java b/remote-api/src/test/java/org/alfresco/rest/api/impl/SizeDetailsImplTest.java index 1cd2c1fa21..d510b144ed 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/impl/SizeDetailsImplTest.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/impl/SizeDetailsImplTest.java @@ -25,6 +25,13 @@ */ package org.alfresco.rest.api.impl; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.Serializable; +import java.util.Map; + import org.alfresco.repo.action.executer.NodeSizeDetailActionExecutor; import org.alfresco.repo.cache.SimpleCache; import org.alfresco.rest.api.Nodes; @@ -39,27 +46,19 @@ import org.alfresco.service.namespace.QName; import org.junit.Before; import org.junit.Test; -import java.io.Serializable; -import java.util.Map; - -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - /** * Unit tests for {@link SizeDetailsImpl} class. - * */ public class SizeDetailsImplTest { private final static int DEFAULT_ITEMS = 1000; + private static final String NAMESPACE = "http://www.alfresco.org/test/NodeSizeDetailsTest"; + private static final QName TYPE_FOLDER = QName.createQName(NAMESPACE, "folder"); private SizeDetailsImpl sizeDetailsImpl; private Nodes nodes; private NodeService nodeService; private ActionService actionService; private Action action; - private static final String NAMESPACE = "http://www.alfresco.org/test/NodeSizeDetailsTest"; - private static final QName TYPE_FOLDER = QName.createQName(NAMESPACE, "folder"); @Before public void setUp() @@ -70,7 +69,7 @@ public class SizeDetailsImplTest PermissionService permissionService = mock(PermissionService.class); actionService = mock(ActionService.class); action = mock(Action.class); - SimpleCache> simpleCache = mock(SimpleCache.class); + SimpleCache> simpleCache = mock(SimpleCache.class); sizeDetailsImpl.setNodes(nodes); sizeDetailsImpl.setNodeService(nodeService); @@ -106,7 +105,7 @@ public class SizeDetailsImplTest NodeSizeDetails requestSizeDetails = sizeDetailsImpl.generateNodeSizeDetailsRequest(nodeId); assertNotNull("After executing POST/size-details, it will provide with 202 status code", requestSizeDetails); - NodeSizeDetails nodeSizeDetails = sizeDetailsImpl.getNodeSizeDetails(nodeId,jobId); + NodeSizeDetails nodeSizeDetails = sizeDetailsImpl.getNodeSizeDetails(nodeId, jobId); assertNotNull("After executing GET/size-details, it will provide with 200 status code", nodeSizeDetails); } diff --git a/remote-api/src/test/java/org/alfresco/rest/api/tests/NodeSizeDetailsTest.java b/remote-api/src/test/java/org/alfresco/rest/api/tests/NodeSizeDetailsTest.java index 4ded97e882..a227b98ec2 100644 --- a/remote-api/src/test/java/org/alfresco/rest/api/tests/NodeSizeDetailsTest.java +++ b/remote-api/src/test/java/org/alfresco/rest/api/tests/NodeSizeDetailsTest.java @@ -25,12 +25,24 @@ */ package org.alfresco.rest.api.tests; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.model.NodeSizeDetails; import org.alfresco.rest.api.model.Site; import org.alfresco.rest.api.tests.client.HttpResponse; import org.alfresco.rest.api.tests.client.PublicApiClient; -import org.alfresco.rest.api.tests.client.data.*; +import org.alfresco.rest.api.tests.client.data.ContentInfo; +import org.alfresco.rest.api.tests.client.data.Document; +import org.alfresco.rest.api.tests.client.data.Node; +import org.alfresco.rest.api.tests.client.data.UserInfo; import org.alfresco.rest.api.tests.util.RestApiUtil; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.site.SiteVisibility; @@ -45,20 +57,11 @@ import org.junit.runners.MethodSorters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; - /** * V1 REST API tests for calculating and retrieving Folder size. */ -@FixMethodOrder (MethodSorters.NAME_ASCENDING) -@RunWith (JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(JUnit4.class) public class NodeSizeDetailsTest extends AbstractBaseApiTest { private static final Logger LOG = LoggerFactory.getLogger(NodeSizeDetailsTest.class); @@ -102,7 +105,7 @@ public class NodeSizeDetailsTest extends AbstractBaseApiTest setRequestContext(user1); String siteTitle = "RandomSite" + System.currentTimeMillis(); - this.userOneN1Site = createSite("RN"+RUNID, siteTitle, siteTitle, SiteVisibility.PRIVATE, 201); + this.userOneN1Site = createSite("RN" + RUNID, siteTitle, siteTitle, SiteVisibility.PRIVATE, 201); // Create a folder within the site document's library. String folderName = "folder" + System.currentTimeMillis(); @@ -123,9 +126,11 @@ public class NodeSizeDetailsTest extends AbstractBaseApiTest // Perform POST request HttpResponse postResponse = post(generateNodeSizeDetailsUrl(folderId), null, 202); - assertNotNull("After executing POST/size-details first time, it will provide jobId with 202 status code",postResponse.getJsonResponse()); + assertNotNull("After executing POST/size-details first time, it will provide jobId with 202 status code", + postResponse.getJsonResponse()); - String jobId = NodeSizeDetails.parseJson((JSONObject)postResponse.getJsonResponse().get("entry")); + String jobId = NodeSizeDetails.parseJson((JSONObject) postResponse.getJsonResponse() + .get("entry")); assertNotNull("In response, JobId should be present", jobId); @@ -136,11 +141,13 @@ public class NodeSizeDetailsTest extends AbstractBaseApiTest HttpResponse getResponse = getSingle(getNodeSizeDetailsUrl(folderId, jobId), null, 200); - assertNotNull("After executing GET/size-details, it will provide NodeSizeDetails with 200 status code",getResponse.getJsonResponse()); + assertNotNull("After executing GET/size-details, it will provide NodeSizeDetails with 200 status code", + getResponse.getJsonResponse()); String getJsonResponse = String.valueOf(getResponse.getJsonResponse()); - assertTrue("We are not getting correct response "+getJsonResponse,getJsonResponse.contains("size") || getJsonResponse.contains("status")); + assertTrue("We are not getting correct response " + getJsonResponse, + getJsonResponse.contains("size") || getJsonResponse.contains("status")); } @Test @@ -149,14 +156,14 @@ public class NodeSizeDetailsTest extends AbstractBaseApiTest setRequestContext(user1); UserInfo userInfo = new UserInfo(user1); - String folder0Name = "f0-testParentFolder-"+RUNID; - String parentFolder = createFolder(tDocLibNodeId, folder0Name,null).getId(); + String folder0Name = "f0-testParentFolder-" + RUNID; + String parentFolder = createFolder(tDocLibNodeId, folder0Name, null).getId(); - for(int i=1;i<=500;i++) + for (int i = 1; i <= 500; i++) { - String folderBName = "folder"+i+RUNID + "_B"; + String folderBName = "folder" + i + RUNID + "_B"; String folderBId = createFolder(parentFolder, folderBName, null).getId(); - String fileName = "content"+i+ RUNID + ".txt"; + String fileName = "content" + i + RUNID + ".txt"; Document d1 = new Document(); d1.setIsFolder(false); d1.setParentId(folderBId); @@ -173,14 +180,17 @@ public class NodeSizeDetailsTest extends AbstractBaseApiTest assertEquals(500, nodes.size()); //Start Time before triggering POST/size-details API - LocalTime expectedTime = LocalTime.now().plusSeconds(5); + LocalTime expectedTime = LocalTime.now() + .plusSeconds(5); // Perform POST request HttpResponse postResponse = post(generateNodeSizeDetailsUrl(parentFolder), null, 202); - assertNotNull("After executing POST/size-details first time, it will provide jobId with 202 status code",postResponse.getJsonResponse()); + assertNotNull("After executing POST/size-details first time, it will provide jobId with 202 status code", + postResponse.getJsonResponse()); - String jobId = NodeSizeDetails.parseJson((JSONObject)postResponse.getJsonResponse().get("entry")); + String jobId = NodeSizeDetails.parseJson((JSONObject) postResponse.getJsonResponse() + .get("entry")); assertNotNull("In response, JobId should be present", jobId); @@ -191,15 +201,17 @@ public class NodeSizeDetailsTest extends AbstractBaseApiTest HttpResponse getResponse = getSingle(getNodeSizeDetailsUrl(folderId, jobId), null, 200); - assertNotNull("After executing GET/size-details, it will provide NodeSizeDetails with 200 status code",getResponse.getJsonResponse()); + assertNotNull("After executing GET/size-details, it will provide NodeSizeDetails with 200 status code", + getResponse.getJsonResponse()); String getJsonResponse = String.valueOf(getResponse.getJsonResponse()); - assertTrue("We are not getting correct response "+getJsonResponse,getJsonResponse.contains("size") || getJsonResponse.contains("status")); + assertTrue("We are not getting correct response " + getJsonResponse, + getJsonResponse.contains("size") || getJsonResponse.contains("status")); //current Time after executing GET/size-details LocalTime actualTime = LocalTime.now(); - assertTrue("Calculating folder node is taking time greater than 5 seconds ",actualTime.isBefore(expectedTime)); + assertTrue("Calculating folder node is taking time greater than 5 seconds ", actualTime.isBefore(expectedTime)); } /** diff --git a/repository/src/main/java/org/alfresco/repo/action/executer/NodeSizeDetailActionExecutor.java b/repository/src/main/java/org/alfresco/repo/action/executer/NodeSizeDetailActionExecutor.java index ca4397c8a6..64ea947472 100644 --- a/repository/src/main/java/org/alfresco/repo/action/executer/NodeSizeDetailActionExecutor.java +++ b/repository/src/main/java/org/alfresco/repo/action/executer/NodeSizeDetailActionExecutor.java @@ -25,6 +25,17 @@ */ package org.alfresco.repo.action.executer; +import java.io.Serializable; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.alfresco.repo.action.ParameterizedItemAbstractBase; import org.alfresco.repo.cache.SimpleCache; import org.alfresco.service.cmr.action.Action; @@ -34,23 +45,14 @@ import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.util.ISO8601DateFormat; import org.alfresco.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.Serializable; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - /** - * NodeSizeDetailActionExecutor - * Executing Alfresco FTS Query to find size of Folder Node + * NodeSizeDetailActionExecutor + * Executing Alfresco FTS Query to find size of Folder Node */ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase @@ -63,16 +65,20 @@ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase */ public static final String NAME = "folder-size"; public static final String EXCEPTION = "Exception"; + + public static final String IN_PROGRESS = "IN_PROGRESS"; public static final String DEFAULT_SIZE = "default-size"; + private static final String STATUS = "status"; + private static final String ACTION_ID = "actionId"; private static final String FIELD_FACET = "content.size"; - private static final String FACET_QUERY = "content.size:[0 TO "+Integer.MAX_VALUE+"] \"label\": \"large\",\"group\":\"Size\""; + private static final String FACET_QUERY = "content.size:[0 TO " + Integer.MAX_VALUE + "] \"label\": \"large\",\"group\":\"Size\""; private SearchService searchService; private SimpleCache> simpleCache; /** * Set the search service * - * @param searchService the search service + * @param searchService the search service */ public void setSearchService(SearchService searchService) { @@ -82,7 +88,7 @@ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase /** * Set the simpleCache service * - * @param simpleCache the cache service + * @param simpleCache the cache service */ public void setSimpleCache(SimpleCache> simpleCache) { @@ -97,7 +103,10 @@ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase { Serializable serializable = nodeAction.getParameterValue(DEFAULT_SIZE); int defaultItems; - Map response = new HashMap<>(); + Map response = new HashMap<>(); + response.put(STATUS, IN_PROGRESS); + response.put(ACTION_ID, nodeAction.getId()); + simpleCache.put(actionedUponNodeRef.getId(), response); try { @@ -106,8 +115,9 @@ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase catch (NumberFormatException numberFormatException) { LOG.error("Exception occurred while parsing String to INT: {} ", numberFormatException.getMessage()); - response.put(EXCEPTION,"Exception occurred while parsing String to INT: {} " + numberFormatException.getMessage()); - simpleCache.put(actionedUponNodeRef.getId(),response); + response.put(EXCEPTION, + "Exception occurred while parsing String to INT: {} " + numberFormatException.getMessage()); + simpleCache.put(actionedUponNodeRef.getId(), response); throw numberFormatException; } @@ -122,38 +132,30 @@ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase { // executing Alfresco FTS facet query. results = facetQuery(nodeRef); - totalItems = Math.min(results.getFieldFacet(FIELD_FACET).size(), defaultItems); - // Using AtomicLong to accumulate the total size. - AtomicLong resultSize = new AtomicLong(0); + totalItems = Math.min(results.getFieldFacet(FIELD_FACET) + .size(), defaultItems); while (!isCalculationCompleted) { - List> pairSizes = results.getFieldFacet(FIELD_FACET).subList(skipCount, totalItems); - pairSizes.parallelStream().forEach(id -> { - try - { - if(id.getSecond()>0) - { - resultSize.addAndGet(Long.valueOf(id.getFirst()) * id.getSecond()); - } - } - catch (Exception e) - { - resultSize.addAndGet(0); - } - }); + List> pairSizes = results.getFieldFacet(FIELD_FACET) + .subList(skipCount, totalItems); + long total = pairSizes.parallelStream() + .mapToLong(id -> Long.parseLong(id.getFirst()) * id.getSecond()) + .sum(); - totalSizeFromFacet+=resultSize.longValue(); - resultSize.set(0); + totalSizeFromFacet += total; - if (results.getFieldFacet(FIELD_FACET).size() <= totalItems || results.getFieldFacet(FIELD_FACET).size() <= defaultItems) + if (results.getFieldFacet(FIELD_FACET) + .size() <= totalItems || results.getFieldFacet(FIELD_FACET) + .size() <= defaultItems) { isCalculationCompleted = true; } else { skipCount += defaultItems; - int remainingItems = results.getFieldFacet(FIELD_FACET).size() - totalItems; + int remainingItems = results.getFieldFacet(FIELD_FACET) + .size() - totalItems; totalItems += Math.min(remainingItems, defaultItems); } } @@ -161,8 +163,9 @@ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase catch (RuntimeException runtimeException) { LOG.error("Exception occurred in NodeSizeDetailActionExecutor:results {} ", runtimeException.getMessage()); - response.put(EXCEPTION,"Exception occurred in NodeSizeDetailActionExecutor:results {} "+runtimeException.getMessage()); - simpleCache.put(nodeRef.getId(),response); + response.put(EXCEPTION, "Exception occurred in NodeSizeDetailActionExecutor:results {} " + + runtimeException.getMessage()); + simpleCache.put(nodeRef.getId(), response); throw runtimeException; } @@ -170,23 +173,27 @@ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase final LocalDateTime eventTimestamp = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss"); String formattedTimestamp = eventTimestamp.format(formatter); + + Date date = Calendar.getInstance() + .getTime(); + String dateStr = ISO8601DateFormat.format(date); + response.put("nodeId", nodeRef.getId()); response.put("size", totalSizeFromFacet); - response.put("calculatedAt", formattedTimestamp); - response.put("numberOfFiles", results != null ? results.getNodeRefs().size() : 0); + response.put("calculatedAt", dateStr); + response.put("numberOfFiles", results != null ? results.getNodeRefs() + .size() : 0); response.put("actionId", nodeAction.getId()); - if(isCalculationCompleted) + if (isCalculationCompleted) { - simpleCache.put(nodeRef.getId(),response); + simpleCache.put(nodeRef.getId(), response); } } protected ResultSet facetQuery(NodeRef nodeRef) { - StringBuilder aftsQuery = new StringBuilder(); - aftsQuery.append("ANCESTOR:\"").append(nodeRef).append("\" AND TYPE:content"); - String query = aftsQuery.toString(); + String query = "ANCESTOR:\"" + nodeRef + "\" AND TYPE:content"; SearchParameters searchParameters = new SearchParameters(); searchParameters.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); @@ -196,7 +203,8 @@ public class NodeSizeDetailActionExecutor extends ActionExecuterAbstractBase searchParameters.addFacetQuery(FACET_QUERY); final SearchParameters.FieldFacet ff = new SearchParameters.FieldFacet(FIELD_FACET); - ff.setLimitOrNull(resultsWithoutFacet.getNodeRefs().size()); + ff.setLimitOrNull(resultsWithoutFacet.getNodeRefs() + .size()); searchParameters.addFieldFacet(ff); resultsWithoutFacet.close(); return searchService.query(searchParameters); diff --git a/repository/src/test/java/org/alfresco/repo/action/executer/NodeSizeDetailsActionExecutorTest.java b/repository/src/test/java/org/alfresco/repo/action/executer/NodeSizeDetailsActionExecutorTest.java index 9fc044bda0..637764d4a6 100644 --- a/repository/src/test/java/org/alfresco/repo/action/executer/NodeSizeDetailsActionExecutorTest.java +++ b/repository/src/test/java/org/alfresco/repo/action/executer/NodeSizeDetailsActionExecutorTest.java @@ -45,27 +45,24 @@ import org.springframework.transaction.annotation.Transactional; @Transactional public class NodeSizeDetailsActionExecutorTest extends BaseSpringTest { + /** + * Id used to identify the test action created + */ + private final static String ID = GUID.generate(); /** * The test node reference */ private NodeRef nodeRef; - /** * The folder Size executer */ private NodeSizeDetailActionExecutor executer; - - /** - * Id used to identify the test action created - */ - private final static String ID = GUID.generate(); - /** * Set the simpleCache service * * @param simpleCache the cache service */ - private SimpleCache> simpleCache; + private SimpleCache> simpleCache; /** * Called at the begining of all tests. @@ -73,29 +70,26 @@ public class NodeSizeDetailsActionExecutorTest extends BaseSpringTest @Before public void before() throws Exception { - NodeService nodeService = (NodeService)this.applicationContext.getBean("nodeService"); + NodeService nodeService = (NodeService) this.applicationContext.getBean("nodeService"); StoreRef testStoreRef; NodeRef rootNodeRef; - AuthenticationComponent authenticationComponent = (AuthenticationComponent)applicationContext.getBean("authenticationComponent"); + AuthenticationComponent authenticationComponent = + (AuthenticationComponent) applicationContext.getBean("authenticationComponent"); authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); // Create the store and get the root node - testStoreRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" - + System.currentTimeMillis()); + testStoreRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis()); rootNodeRef = nodeService.getRootNode(testStoreRef); // Create the node used for tests - this.nodeRef = nodeService.createNode( - rootNodeRef, - ContentModel.ASSOC_CHILDREN, - QName.createQName("{test}testnode"), - ContentModel.TYPE_CONTENT).getChildRef(); + this.nodeRef = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, + QName.createQName("{test}testnode"), ContentModel.TYPE_CONTENT).getChildRef(); // Get the executer instance. - this.executer = (NodeSizeDetailActionExecutor)this.applicationContext.getBean(NodeSizeDetailActionExecutor.NAME); + this.executer = (NodeSizeDetailActionExecutor) this.applicationContext.getBean(NodeSizeDetailActionExecutor.NAME); - simpleCache = (SimpleCache>) this.applicationContext.getBean("folderSizeSharedCache"); + simpleCache = (SimpleCache>) this.applicationContext.getBean("folderSizeSharedCache"); } /** @@ -109,7 +103,7 @@ public class NodeSizeDetailsActionExecutorTest extends BaseSpringTest action.setParameterValue(NodeSizeDetailActionExecutor.DEFAULT_SIZE, maxItems); this.executer.executeImpl(action, this.nodeRef); Object resultAction = simpleCache.get(this.nodeRef.getId()); - Map mapResult = (Map)resultAction; - assertTrue(mapResult != null); + Map mapResult = (Map) resultAction; + assertNotNull(mapResult); } } \ No newline at end of file