diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml index 775cb44d97..a4b2c6dfce 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/classified-content-context.xml @@ -229,6 +229,7 @@ org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService.getCurrentClassification=ACL_ALLOW org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService.classifyContent=ACL_ALLOW org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService.hasClearance=ACL_ALLOW + org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService.editClassifiedContent=ACL_ALLOW org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService.*=ACL_DENY diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationService.java index 227bac1c9e..2f4428c57c 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationService.java @@ -30,6 +30,7 @@ import org.alfresco.service.cmr.repository.NodeRef; * A service to handle the classification of content. * * @author tpage + * @since 3.0 */ public interface ContentClassificationService { @@ -50,7 +51,7 @@ public interface ContentClassificationService * @param classificationReasonIds A non-empty set of ids of reasons for classifying the content in this way. * @param content The node to classify. * @throws LevelIdNotFound If the supplied level id is not found. - * @thorws IllegalArgumentException If the supplied {@code classifiedBy} is {@code null}, + * @throws IllegalArgumentException If the supplied {@code classifiedBy} is {@code null}, * the empty string or a string consisting only of whitespace. * @throws ReasonIdNotFound If any of the supplied reason ids are not found. * @throws InvalidNodeRefException If the node could not be found. @@ -60,6 +61,25 @@ public interface ContentClassificationService Set classificationReasonIds, NodeRef content) throws LevelIdNotFound, ReasonIdNotFound, InvalidNodeRefException, InvalidNode; + /** + * Edits the classified content. + * + * @param classificationLevelId The security clearance needed to access the content. + * @param classifiedBy Free-form text identifying who edited the classified content. + * @param classificationAgency The name of the agency responsible for editing the classified content. + * @param classificationReasonIds A non-empty set of ids of reasons for editing the classified content in this way. + * @param content The classified content which will be edited. + * @throws LevelIdNotFound If the supplied level id is not found. + * @throws IllegalArgumentException If the supplied {@code classifiedBy} is {@code null}, + * the empty string or a string consisting only of whitespace. + * @throws ReasonIdNotFound If any of the supplied reason ids are not found. + * @throws InvalidNodeRefException If the node could not be found. + * @throws InvalidNode If the supplied node is not a content node. + */ + void editClassifiedContent(String classificationLevelId, String classifiedBy, String classificationAgency, + Set classificationReasonIds, NodeRef content) + throws LevelIdNotFound, ReasonIdNotFound, InvalidNodeRefException, InvalidNode; + /** * Checks if the node is classified or not. A node classified * as "Unclassified" will be treated as not classified. diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java index 19cf809500..3682a1091e 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImpl.java @@ -32,10 +32,12 @@ import org.alfresco.model.ContentModel; import org.alfresco.model.QuickShareModel; import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.InvalidNode; import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.LevelIdNotFound; +import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationException.ReasonIdNotFound; import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; @@ -43,6 +45,7 @@ import org.alfresco.service.namespace.QName; * A service to handle the classification of content. * * @author tpage + * @since 3.0 */ public class ContentClassificationServiceImpl extends ServiceBaseImpl implements ContentClassificationService, ClassifiedContentModel @@ -63,6 +66,9 @@ public class ContentClassificationServiceImpl extends ServiceBaseImpl this.reasonManager = classificationServiceBootstrap.getClassificationReasonManager(); } + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService#getCurrentClassification(org.alfresco.service.cmr.repository.NodeRef) + */ @Override public ClassificationLevel getCurrentClassification(final NodeRef nodeRef) { @@ -84,12 +90,16 @@ public class ContentClassificationServiceImpl extends ServiceBaseImpl }); }; + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService#classifyContent(java.lang.String, java.lang.String, java.lang.String, java.util.Set, org.alfresco.service.cmr.repository.NodeRef) + */ @Override public void classifyContent(String classificationLevelId, String classifiedBy, String classificationAgency, Set classificationReasonIds, final NodeRef content) { checkNotBlank("classificationLevelId", classificationLevelId); checkNotBlank("classifiedBy", classifiedBy); + // classificationAgency can be blank mandatory("classificationReasonIds", classificationReasonIds); mandatory("content", content); @@ -97,11 +107,6 @@ public class ContentClassificationServiceImpl extends ServiceBaseImpl { throw new InvalidNode(content, "The supplied node is not a content node."); } - if (nodeService.hasAspect(content, ASPECT_CLASSIFIED)) - { - throw new UnsupportedOperationException( - "The content has already been classified. Reclassification is currently not supported."); - } if (nodeService.hasAspect(content, QuickShareModel.ASPECT_QSHARE)) { throw new IllegalStateException("A shared content cannot be classified."); @@ -147,6 +152,9 @@ public class ContentClassificationServiceImpl extends ServiceBaseImpl }, authenticationUtil.getAdminUserName()); } + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService#hasClearance(org.alfresco.service.cmr.repository.NodeRef) + */ @Override public boolean hasClearance(NodeRef nodeRef) { @@ -174,4 +182,21 @@ public class ContentClassificationServiceImpl extends ServiceBaseImpl return isClassified; } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.classification.ContentClassificationService#editClassifiedContent(java.lang.String, java.lang.String, java.lang.String, java.util.Set, org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + public void editClassifiedContent(String classificationLevelId, String classifiedBy, String classificationAgency, + Set classificationReasonIds, NodeRef content) + throws LevelIdNotFound, ReasonIdNotFound, InvalidNodeRefException, InvalidNode + { + checkNotBlank("classificationLevelId", classificationLevelId); + checkNotBlank("classifiedBy", classifiedBy); + // classificationAgency can be blank + mandatory("classificationReasonIds", classificationReasonIds); + mandatory("content", content); + + classifyContent(classificationLevelId, classifiedBy, classificationAgency, classificationReasonIds, content); + } } diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImplUnitTest.java index 02d5c28d7f..c51e2e6444 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/ContentClassificationServiceImplUnitTest.java @@ -64,6 +64,7 @@ import com.google.common.collect.Sets; * Unit tests for {@link ContentClassificationServiceImpl}. * * @author tpage + * @since 3.0 */ public class ContentClassificationServiceImplUnitTest implements ClassifiedContentModel { @@ -138,20 +139,6 @@ public class ContentClassificationServiceImplUnitTest implements ClassifiedConte Sets.newHashSet("reasonId1", "reasonId2"), notAPieceOfContent); } - /** Classify a piece of content that has already been classified. */ - @Test(expected = UnsupportedOperationException.class) - public void classifyContent_alreadyClassified() - { - // Create a classified piece of content. - NodeRef classifiedContent = new NodeRef("classified://content/"); - when(mockDictionaryService.isSubClass(mockNodeService.getType(classifiedContent), ContentModel.TYPE_CONTENT)).thenReturn(true); - when(mockNodeService.hasAspect(classifiedContent, ClassifiedContentModel.ASPECT_CLASSIFIED)).thenReturn(true); - - // Call the method under test. - contentClassificationServiceImpl.classifyContent("levelId1", "classifiedBy", "classificationAgency", - Sets.newHashSet("reasonId1", "reasonId2"), classifiedContent); - } - /** Classify a piece of content that has already been shared */ @Test(expected = IllegalStateException.class) public void classifySharedContent()