diff --git a/source/java/org/alfresco/repo/version/VersionServiceImplTest.java b/source/java/org/alfresco/repo/version/VersionServiceImplTest.java index 0dad82b2a0..83cbd59254 100644 --- a/source/java/org/alfresco/repo/version/VersionServiceImplTest.java +++ b/source/java/org/alfresco/repo/version/VersionServiceImplTest.java @@ -62,7 +62,7 @@ import org.springframework.context.ApplicationContext; /** * versionService test class. * - * @author Roy Wetherall + * @author Roy Wetherall, janv */ public class VersionServiceImplTest extends BaseVersionStoreTest { @@ -937,7 +937,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest assertNotNull(versionHistory); assertEquals(1, versionHistory.getAllVersions().size()); - nodeService.setProperty(versionableNode, ContentModel.PROP_AUTHOR, "ano author"); + nodeService.setProperty(versionableNode, ContentModel.PROP_AUTHOR, "ano author 1"); return null; } @@ -975,7 +975,7 @@ public class VersionServiceImplTest extends BaseVersionStoreTest assertNotNull(versionHistory); assertEquals(1, versionHistory.getAllVersions().size()); - nodeService.setProperty(versionableNode2, ContentModel.PROP_AUTHOR, "ano author"); + nodeService.setProperty(versionableNode2, ContentModel.PROP_AUTHOR, "ano author 2"); return null; } @@ -996,6 +996,112 @@ public class VersionServiceImplTest extends BaseVersionStoreTest }); } + public void testAutoVersionOnUpdatePropsOnlyWithExcludes() + { + // test auto-version props on - without any excludes + final NodeRef versionableNode = createNewVersionableNode(); + this.dbNodeService.setProperty(versionableNode, ContentModel.PROP_AUTO_VERSION_PROPS, true); + + setComplete(); + endTransaction(); + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + VersionHistory versionHistory = versionService.getVersionHistory(versionableNode); + assertNotNull(versionHistory); + assertEquals(1, versionHistory.getAllVersions().size()); + + nodeService.setProperty(versionableNode, ContentModel.PROP_AUTHOR, "ano author 1"); + nodeService.setProperty(versionableNode, ContentModel.PROP_DESCRIPTION, "description 1"); + + return null; + } + }); + + // Now lets have a look and make sure we have the correct number of entries in the version history + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + VersionHistory versionHistory = versionService.getVersionHistory(versionableNode); + assertNotNull(versionHistory); + assertEquals(2, versionHistory.getAllVersions().size()); + + return null; + } + + }); + + VersionableAspect versionableAspect = (VersionableAspect)applicationContext.getBean("versionableAspect"); + + List excludedOnUpdateProps = new ArrayList(1); + excludedOnUpdateProps.add(ContentModel.PROP_AUTHOR.toPrefixString()); + versionableAspect.setExcludedOnUpdateProps(excludedOnUpdateProps); + + // test auto-version props on - with an excluded prop change + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + VersionHistory versionHistory = versionService.getVersionHistory(versionableNode); + assertNotNull(versionHistory); + assertEquals(2, versionHistory.getAllVersions().size()); + + nodeService.setProperty(versionableNode, ContentModel.PROP_AUTHOR, "ano author 2"); + nodeService.setProperty(versionableNode, ContentModel.PROP_DESCRIPTION, "description 2"); + + return null; + } + }); + + // Now lets have a look and make sure we have the correct number of entries in the version history + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + VersionHistory versionHistory = versionService.getVersionHistory(versionableNode); + assertNotNull(versionHistory); + assertEquals(2, versionHistory.getAllVersions().size()); + + return null; + } + + }); + + // test auto-version props on - with a non-excluded prop change + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + VersionHistory versionHistory = versionService.getVersionHistory(versionableNode); + assertNotNull(versionHistory); + assertEquals(2, versionHistory.getAllVersions().size()); + + nodeService.setProperty(versionableNode, ContentModel.PROP_DESCRIPTION, "description 3"); + + return null; + } + }); + + // Now lets have a look and make sure we have the correct number of entries in the version history + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Object execute() throws Exception + { + VersionHistory versionHistory = versionService.getVersionHistory(versionableNode); + assertNotNull(versionHistory); + assertEquals(3, versionHistory.getAllVersions().size()); + + return null; + } + + }); + } + public void testAR807() { QName prop = QName.createQName("http://www.alfresco.org/test/versionstorebasetest/1.0", "intProp"); diff --git a/source/java/org/alfresco/repo/version/VersionableAspect.java b/source/java/org/alfresco/repo/version/VersionableAspect.java index 80a18a9238..3cdef372f4 100644 --- a/source/java/org/alfresco/repo/version/VersionableAspect.java +++ b/source/java/org/alfresco/repo/version/VersionableAspect.java @@ -27,6 +27,7 @@ package org.alfresco.repo.version; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.alfresco.i18n.I18NUtil; @@ -48,6 +49,7 @@ import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.VersionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.EqualsHelper; /** * Class containing behaviour for the versionable aspect @@ -79,6 +81,13 @@ public class VersionableAspect implements ContentServicePolicies.OnContentUpdate /** The Version service */ private VersionService versionService; + /** + * Optional list of excluded props + * - only applies if cm:autoVersionOnUpdateProps=true (and cm:autoVersion=true) + * - if any one these props changes then "auto version on prop update" does not occur (even if there are other property changes) + */ + private List excludedOnUpdateProps = Collections.emptyList(); + /** * Set the policy component * @@ -109,6 +118,11 @@ public class VersionableAspect implements ContentServicePolicies.OnContentUpdate this.nodeService = nodeService; } + public void setExcludedOnUpdateProps(List excludedOnUpdateProps) + { + this.excludedOnUpdateProps = excludedOnUpdateProps; + } + /** * Initialise the versionable aspect policies */ @@ -334,6 +348,43 @@ public class VersionableAspect implements ContentServicePolicies.OnContentUpdate if ((autoVersion == true) && (autoVersionProps == true)) { + // Check for explicitly excluded props - if one or more excluded props changes then do not auto-version on this event (even if other props changed) + if (excludedOnUpdateProps.size() > 0) + { + Map propNames = new HashMap(after.size()); + for (QName afterProp : after.keySet()) + { + if (excludedOnUpdateProps.contains(afterProp.getPrefixString())) + { + propNames.put(afterProp.getPrefixString(), afterProp); + } + } + for (QName beforeProp : before.keySet()) + { + if (excludedOnUpdateProps.contains(beforeProp.getPrefixString())) + { + propNames.put(beforeProp.getPrefixString(), beforeProp); + } + } + + if (propNames.size() > 0) + { + for (QName prop : propNames.values()) + { + Serializable beforeValue = before.get(prop); + Serializable afterValue = after.get(prop); + + if (EqualsHelper.nullSafeEquals(beforeValue, afterValue) != true) + { + // excluded - do not version + return; + } + } + } + + // drop through and auto-version + } + // Create the auto-version Map versionProperties = new HashMap(1); versionProperties.put(Version.PROP_DESCRIPTION, I18NUtil.getMessage(MSG_AUTO_VERSION_PROPS));