getRelationshipsFrom(NodeRef nodeRef);
-
+
/**
- * Gets all the relationships that go in to the given node reference
+ * Gets all the relationships that come out from the given node reference
+ * that match the a given name filter.
+ *
+ * Exact match only.
*
* @param nodeRef The node reference
- * @return All relationships that go in to the given node reference
+ * @param nameFilter Name filter for results
+ * @return All relationships that come out from the given node reference
+ *
+ * @since 2.3.1
+ */
+ Set getRelationshipsFrom(NodeRef nodeRef, String nameFilter);
+
+ /**
+ * Gets all the relationships that go into the given node reference
+ *
+ * @param nodeRef The node reference
+ * @return All relationships that go into the given node reference
*/
Set getRelationshipsTo(NodeRef nodeRef);
+
+ /**
+ * Gets all the relationships that go into the given node reference
+ * that match the a given name filter.
+ *
+ * Exact match only.
+ *
+ * @param nodeRef The node reference
+ * @param nameFilter Name filter for results
+ * @return All relationships that go into the given node reference
+ *
+ * @since 2.3.1
+ */
+ Set getRelationshipsTo(NodeRef nodeRef, String nameFilter);
/**
* Adds a relationship from the given node source
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/relationship/RelationshipServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/relationship/RelationshipServiceImpl.java
index 92b4fa7be4..df7487e6ad 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/relationship/RelationshipServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/relationship/RelationshipServiceImpl.java
@@ -376,16 +376,25 @@ public class RelationshipServiceImpl extends RecordsManagementAdminBase implemen
*/
@Override
public Set getRelationshipsFrom(NodeRef nodeRef)
+ {
+ return getRelationshipsFrom(nodeRef, null);
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#getRelationshipsFrom(org.alfresco.service.cmr.repository.NodeRef, String)
+ */
+ @Override
+ public Set getRelationshipsFrom(NodeRef nodeRef, String nameFilter)
{
mandatory("nodeRef", nodeRef);
Set relationships = new HashSet();
List customReferencesFrom = getNodeService().getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
- relationships.addAll(generateRelationshipFromAssociationRef(customReferencesFrom));
+ relationships.addAll(generateRelationshipFromAssociationRef(customReferencesFrom, nameFilter));
List customChildReferences = getNodeService().getChildAssocs(nodeRef);
- relationships.addAll(generateRelationshipFromParentChildAssociationRef(customChildReferences));
+ relationships.addAll(generateRelationshipFromParentChildAssociationRef(customChildReferences, nameFilter));
return relationships;
}
@@ -395,20 +404,29 @@ public class RelationshipServiceImpl extends RecordsManagementAdminBase implemen
*/
@Override
public Set getRelationshipsTo(NodeRef nodeRef)
+ {
+ return getRelationshipsTo(nodeRef, null);
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#getRelationshipsTo(org.alfresco.service.cmr.repository.NodeRef, String)
+ */
+ @Override
+ public Set getRelationshipsTo(NodeRef nodeRef, String nameFilter)
{
mandatory("nodeRef", nodeRef);
Set relationships = new HashSet();
List customReferencesTo = getNodeService().getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
- relationships.addAll(generateRelationshipFromAssociationRef(customReferencesTo));
+ relationships.addAll(generateRelationshipFromAssociationRef(customReferencesTo, nameFilter));
List customParentReferences = getNodeService().getParentAssocs(nodeRef);
- relationships.addAll(generateRelationshipFromParentChildAssociationRef(customParentReferences));
+ relationships.addAll(generateRelationshipFromParentChildAssociationRef(customParentReferences, nameFilter));
return relationships;
}
-
+
/**
* @see org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService#addRelationship(java.lang.String, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
*/
@@ -418,7 +436,19 @@ public class RelationshipServiceImpl extends RecordsManagementAdminBase implemen
mandatoryString("uniqueName", uniqueName);
mandatory("source", source);
mandatory("target", target);
-
+
+ // check the source node exists
+ if (!getNodeService().exists(source))
+ {
+ throw new AlfrescoRuntimeException("Can't create relationship '" + uniqueName + "', because source node doesn't exist.");
+ }
+
+ // check the target node exists
+ if (!getNodeService().exists(target))
+ {
+ throw new AlfrescoRuntimeException("Can't create relationship " + uniqueName + ", because target node doesn't exist.");
+ }
+
if (getNodeService().hasAspect(target, ASPECT_FROZEN))
{
StringBuilder sb = new StringBuilder();
@@ -622,14 +652,15 @@ public class RelationshipServiceImpl extends RecordsManagementAdminBase implemen
* @param associationRefs Association references
* @return Relationships generated from the given association references
*/
- private Set generateRelationshipFromAssociationRef(List associationRefs)
+ private Set generateRelationshipFromAssociationRef(List associationRefs, String nameFilter)
{
Set relationships = new HashSet();
for (AssociationRef associationRef : associationRefs)
{
String uniqueName = associationRef.getTypeQName().getLocalName();
- if (existsRelationshipDefinition(uniqueName))
+ if (existsRelationshipDefinition(uniqueName) &&
+ (nameFilter == null || uniqueName.equals(nameFilter)))
{
NodeRef from = associationRef.getSourceRef();
NodeRef to = associationRef.getTargetRef();
@@ -646,14 +677,15 @@ public class RelationshipServiceImpl extends RecordsManagementAdminBase implemen
* @param childAssociationRefs Child association references
* @return Relationships generated from the given child association references
*/
- private Set generateRelationshipFromParentChildAssociationRef(List childAssociationRefs)
+ private Set generateRelationshipFromParentChildAssociationRef(List childAssociationRefs, String nameFilter)
{
Set relationships = new HashSet();
for (ChildAssociationRef childAssociationRef : childAssociationRefs)
{
String uniqueName = childAssociationRef.getQName().getLocalName();
- if (existsRelationshipDefinition(uniqueName))
+ if (existsRelationshipDefinition(uniqueName)&&
+ (nameFilter == null || uniqueName.equals(nameFilter)))
{
NodeRef from = childAssociationRef.getParentRef();
NodeRef to = childAssociationRef.getChildRef();
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionModel.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionModel.java
index f21b28043d..180b191bfd 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionModel.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionModel.java
@@ -41,6 +41,7 @@ public interface RecordableVersionModel
QName ASPECT_RECORDED_VERSION = QName.createQName(RMV_URI, "recordedVersion");
QName PROP_RECORD_NODE_REF = QName.createQName(RMV_URI, "recordNodeRef");
QName PROP_FROZEN_OWNER = QName.createQName(RMV_URI, "frozenOwner");
+ QName PROP_DESTROYED = QName.createQName(RMV_URI, "destroyed");
/** version record aspect */
QName ASPECT_VERSION_RECORD = QName.createQName(RMV_URI, "versionRecord");
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionNodeServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionNodeServiceImpl.java
index c90dc17da9..78759b8713 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionNodeServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionNodeServiceImpl.java
@@ -21,6 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.version;
import static org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImpl.RECORD_MODEL_URIS;
import java.io.Serializable;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -181,6 +182,7 @@ public class RecordableVersionNodeServiceImpl extends Node2ServiceImpl
/**
* @see org.alfresco.repo.version.Node2ServiceImpl#getAspects(org.alfresco.service.cmr.repository.NodeRef)
*/
+ @SuppressWarnings("unchecked")
@Override
public Set getAspects(NodeRef nodeRef) throws InvalidNodeRefException
{
@@ -190,8 +192,15 @@ public class RecordableVersionNodeServiceImpl extends Node2ServiceImpl
if (dbNodeService.hasAspect(converted, ASPECT_RECORDED_VERSION))
{
NodeRef record = (NodeRef)dbNodeService.getProperty(converted, PROP_RECORD_NODE_REF);
- Set aspects = dbNodeService.getAspects(record);
- return processAspects(aspects);
+ if (dbNodeService.exists(record))
+ {
+ Set aspects = dbNodeService.getAspects(record);
+ return processAspects(aspects);
+ }
+ else
+ {
+ return (Set)Collections.EMPTY_SET;
+ }
}
else
{
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionService.java
index e5b0c8c6f2..15f3757333 100755
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionService.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionService.java
@@ -47,6 +47,23 @@ public interface RecordableVersionService
*/
boolean isRecordedVersion(Version version);
+ /**
+ * If the version is a recorded version, gets the related version
+ * record.
+ *
+ * @param version version
+ * @return NodeRef node reference of version record
+ */
+ NodeRef getVersionRecord(Version version);
+
+ /**
+ * Gets the version that relates to the version record
+ *
+ * @param versionRecord version record node reference
+ * @return Version version or null if not found
+ */
+ Version getRecordedVersion(NodeRef record);
+
/**
* Creates a record from the latest version, marking it as recorded.
*
@@ -54,8 +71,26 @@ public interface RecordableVersionService
* version is already recorded.
*
* @param nodeRef node reference
- * @return NodeRef node reference to the crated record.
+ * @return NodeRef node reference to the created record.
*/
NodeRef createRecordFromLatestVersion(NodeRef filePlan, NodeRef nodeRef);
+
+ /**
+ * Indicates whether a record version is destroyed or not.
+ *
+ * @param version version
+ * @return boolean true if destroyed, false otherwise
+ */
+ boolean isRecordedVersionDestroyed(Version version);
+
+ /**
+ * Marks a recorded version as destroyed.
+ *
+ * Note this method does not destroy the associated record, instead it marks the
+ * version as destroyed.
+ *
+ * @param version version
+ */
+ void destroyRecordedVersion(Version version);
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java
index a148fd3016..417e66fe08 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImpl.java
@@ -55,6 +55,7 @@ import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
import org.alfresco.util.PropertyMap;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -76,7 +77,8 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
public static final String KEY_FILE_PLAN = "file-plan";
/** version record property */
- public static final String PROP_VERSION_RECORD = "RecordVersion";
+ protected static final String PROP_VERSION_RECORD = "RecordVersion";
+ protected static final String PROP_RECORDED_VERSION_DESTROYED = "RecordedVersionDestroyed";
/** version aspect property names */
private static final String[] VERSION_PROPERTY_NAMES = new String[]
@@ -491,7 +493,8 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
{
// look for the associated record
final NodeRef previousRecord = (NodeRef)previousVersion.getVersionProperties().get(PROP_VERSION_RECORD);
- if (previousRecord != null)
+ if (previousRecord != null &&
+ nodeService.exists(previousRecord))
{
versionRecord = previousRecord;
break;
@@ -501,6 +504,29 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
return versionRecord;
}
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService#getRecordedVersion(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ public Version getRecordedVersion(NodeRef versionRecord)
+ {
+ Version version = null;
+ NodeRef versionedNodeRef = (NodeRef) nodeService.getProperty(versionRecord, RecordableVersionModel.PROP_VERSIONED_NODEREF);
+ if (versionedNodeRef != null)
+ {
+ String versionLabel = (String) nodeService.getProperty(versionRecord, RecordableVersionModel.PROP_VERSION_LABEL);
+ if (StringUtils.isNotBlank(versionLabel))
+ {
+ VersionHistory versionHistory = getVersionHistory(versionedNodeRef);
+ if (versionHistory != null)
+ {
+ version = versionHistory.getVersion(versionLabel);
+ }
+ }
+ }
+ return version;
+ }
/**
* Freezes audit aspect properties.
@@ -533,12 +559,18 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
{
Version version = super.getVersion(versionRef);
+ // place the version record reference in the version properties
NodeRef record = (NodeRef)dbNodeService.getProperty(versionRef, PROP_RECORD_NODE_REF);
if (record != null)
- {
+ {
version.getVersionProperties().put(PROP_VERSION_RECORD, record);
}
+ // place information about the destruction of the version record in the properties
+ Boolean destroyed = (Boolean)dbNodeService.getProperty(versionRef, PROP_DESTROYED);
+ if (destroyed == null) { destroyed = Boolean.FALSE; }
+ version.getVersionProperties().put(PROP_RECORDED_VERSION_DESTROYED, destroyed);
+
return version;
}
@@ -579,10 +611,31 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
@Override
public boolean isRecordedVersion(Version version)
{
- boolean result = true;
- if (version.getVersionProperties().get(PROP_VERSION_RECORD) == null)
+ NodeRef versionNodeRef = getVersionNodeRef(version);
+ return dbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION);
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService#getVersionRecord(org.alfresco.service.cmr.version.Version)
+ */
+ @Override
+ public NodeRef getVersionRecord(Version version)
+ {
+ NodeRef result = null;
+ NodeRef versionNodeRef = getVersionNodeRef(version);
+ if (dbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
{
- result = false;
+ // get the version record
+ result = (NodeRef)dbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF);
+
+ // check that the version record exists
+ if (result != null &&
+ !dbNodeService.exists(result))
+ {
+ throw new AlfrescoRuntimeException("Version record node doesn't exist. Indicates version has not been updated "
+ + "when associated version record was deleted. "
+ + "(nodeRef=" + result.toString() + ")");
+ }
}
return result;
}
@@ -737,6 +790,47 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
return record;
}
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService#isRecordedVersionDestroyed(org.alfresco.service.cmr.version.Version)
+ */
+ @Override
+ public boolean isRecordedVersionDestroyed(Version version)
+ {
+ boolean result = false;
+
+ // get the version node reference
+ NodeRef versionNodeRef = getVersionNodeRef(version);
+
+ // get the destroyed property value
+ Boolean isDestroyed = (Boolean)dbNodeService.getProperty(versionNodeRef, PROP_DESTROYED);
+ if (isDestroyed != null)
+ {
+ result = isDestroyed.booleanValue();
+ }
+
+ return result;
+ }
+
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService#destroyRecordedVersion(org.alfresco.service.cmr.version.Version)
+ */
+ @Override
+ public void destroyRecordedVersion(Version version)
+ {
+ // get the version node reference
+ NodeRef versionNodeRef = getVersionNodeRef(version);
+
+ // if it's a recorded version
+ if (dbNodeService.hasAspect(versionNodeRef, ASPECT_RECORDED_VERSION))
+ {
+ // mark it as destroyed
+ dbNodeService.setProperty(versionNodeRef, PROP_DESTROYED, true);
+
+ // clear the record node reference property
+ dbNodeService.setProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF, null);
+ }
+ }
+
/**
* Helper method to get the version number of a given version by inspecting the
* name of the parent association.
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AdHocRecordableVersionsTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AdHocRecordableVersionsTest.java
index c7b1e08f4c..b8a2ed6e94 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AdHocRecordableVersionsTest.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AdHocRecordableVersionsTest.java
@@ -169,7 +169,7 @@ public class AdHocRecordableVersionsTest extends RecordableVersionsBaseTest
public Void doWork() throws Exception
{
// add custom meta-data to record
- NodeRef record = (NodeRef)version.getVersionProperties().get(RecordableVersionServiceImpl.PROP_VERSION_RECORD);
+ NodeRef record = recordableVersionService.getVersionRecord(version);
assertNotNull(record);
recordService.addRecordType(record, TestModel.ASPECT_RECORD_METADATA);
nodeService.setProperty(record, TestModel.PROPERTY_RECORD_METADATA, "Peter Wetherall");
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AutoRecordableVersionsTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AutoRecordableVersionsTest.java
index a9e4d678a3..81a49f3652 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AutoRecordableVersionsTest.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AutoRecordableVersionsTest.java
@@ -24,7 +24,6 @@ import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.relationship.Relationship;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionPolicy;
-import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
@@ -131,7 +130,7 @@ public class AutoRecordableVersionsTest extends RecordableVersionsBaseTest
checkRecordedVersion(dmDocument, null, "0.3");
Version version = versionService.getCurrentVersion(dmDocument);
- NodeRef record = (NodeRef)version.getVersionProperties().get(RecordableVersionServiceImpl.PROP_VERSION_RECORD);
+ NodeRef record = recordableVersionService.getVersionRecord(version);
boolean foundPrevious = false;
Set relationships = relationshipService.getRelationshipsFrom(record);
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AutoVersionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AutoVersionTest.java
new file mode 100755
index 0000000000..99c6eec74d
--- /dev/null
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/AutoVersionTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.module.org_alfresco_module_rm.test.integration.version;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.version.VersionHistory;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.GUID;
+
+
+/**
+ * Test recorded version histories when interacting with cm:versionable aspect
+ * and the auto-version behvaiour.
+ *
+ * @author Roy Wetherall
+ * @since 2.3.1
+ */
+public class AutoVersionTest extends RecordableVersionsBaseTest
+{
+ /**
+ * Given a versionable document
+ * When I specialise the type of the document
+ * Then the version history has only one initial version
+ * And it does not represent the current type of the document
+ */
+ public void testSpecialisedNodeInitialVersionCreated()
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest(dmCollaborator)
+ {
+ private NodeRef myDocument;
+
+ public void given() throws Exception
+ {
+ // create a document
+ myDocument = fileFolderService.create(dmFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
+
+ // make versionable
+ nodeService.addAspect(myDocument, ContentModel.ASPECT_VERSIONABLE, null);
+ }
+
+ public void when()
+ {
+ // specialise document
+ nodeService.setType(myDocument, TYPE_CUSTOM_TYPE);
+ }
+
+ public void then()
+ {
+ VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
+
+ assertNotNull(versionHistory);
+ assertEquals(1, versionHistory.getAllVersions().size());
+
+ NodeRef frozenState = versionHistory.getHeadVersion().getFrozenStateNodeRef();
+ assertEquals(ContentModel.TYPE_CONTENT, nodeService.getType(frozenState));
+ assertEquals(TYPE_CUSTOM_TYPE, nodeService.getType(myDocument));
+ }
+ });
+ }
+
+ /**
+ * Given a versionable document with initial version turned off
+ * When I specialise the type of the document
+ * Then the version history remains empty
+ */
+ public void testSpecialisedNodeInitialVersionNotCreated()
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest(dmCollaborator)
+ {
+ private NodeRef myDocument;
+
+ public void given() throws Exception
+ {
+ // create a document
+ myDocument = fileFolderService.create(dmFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
+
+ // make versionable
+ Map props = new HashMap(1);
+ props.put(ContentModel.PROP_INITIAL_VERSION, false);
+ nodeService.addAspect(myDocument, ContentModel.ASPECT_VERSIONABLE, props);
+ }
+
+ public void when()
+ {
+ // specialise document
+ nodeService.setType(myDocument, TYPE_CUSTOM_TYPE);
+ }
+
+ public void then()
+ {
+ VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
+ assertNull(versionHistory);
+ }
+ });
+ }
+
+
+}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/DeclareAsRecordVersionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/DeclareAsRecordVersionTest.java
index d6e33fb515..31e4a430dc 100755
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/DeclareAsRecordVersionTest.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/DeclareAsRecordVersionTest.java
@@ -28,6 +28,7 @@ import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType;
+import org.alfresco.util.GUID;
/**
* Declare as record version integration tests
@@ -99,7 +100,7 @@ public class DeclareAsRecordVersionTest extends RecordableVersionsBaseTest
/**
* Given versionable content with a recorded latest version
- * When I delcare a version record
+ * When I declare a version record
* Then nothing happens since the latest version is already recorded
* And a warning is logged
*/
@@ -146,5 +147,62 @@ public class DeclareAsRecordVersionTest extends RecordableVersionsBaseTest
});
}
+ /**
+ * Given that a document is a specialized type
+ * When version is declared as a record
+ * Then the record is the same type as the source document
+ *
+ * @see https://issues.alfresco.com/jira/browse/RM-2194
+ */
+ public void testSpecializedContentType()
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest(dmCollaborator)
+ {
+ private NodeRef customDocument;
+ private NodeRef versionRecord;
+ private Map versionProperties;
+
+ public void given() throws Exception
+ {
+ // create content
+ customDocument = fileFolderService.create(dmFolder, GUID.generate(), TYPE_CUSTOM_TYPE).getNodeRef();
+ prepareContent(customDocument);
+
+ // setup version properties
+ versionProperties = new HashMap(2);
+ versionProperties.put(Version.PROP_DESCRIPTION, DESCRIPTION);
+ versionProperties.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
+
+ // create version
+ versionService.createVersion(customDocument, versionProperties);
+
+ // assert that the latest version is not recorded
+ assertFalse(recordableVersionService.isCurrentVersionRecorded(customDocument));
+ }
+
+ public void when()
+ {
+ // create version record from latest version
+ versionRecord = recordableVersionService.createRecordFromLatestVersion(filePlan, customDocument);
+ }
+
+ public void then()
+ {
+ // check the created record
+ assertNotNull(versionRecord);
+ assertTrue(recordService.isRecord(versionRecord));
+
+ // check the record type is correct
+ assertEquals(TYPE_CUSTOM_TYPE, nodeService.getType(versionRecord));
+
+ // assert the current version is recorded
+ assertTrue(recordableVersionService.isCurrentVersionRecorded(customDocument));
+
+ // check the recorded version
+ checkRecordedVersion(customDocument, DESCRIPTION, "0.1");
+ }
+ });
+
+ }
}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/DeleteRecordVersionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/DeleteRecordVersionTest.java
new file mode 100644
index 0000000000..8f716cc4fe
--- /dev/null
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/DeleteRecordVersionTest.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2005-2014 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.module.org_alfresco_module_rm.test.integration.version;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.action.impl.CompleteEventAction;
+import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction;
+import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction;
+import org.alfresco.module.org_alfresco_module_rm.relationship.Relationship;
+import org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService;
+import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils;
+import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
+import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionPolicy;
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.service.cmr.repository.ContentWriter;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.version.Version;
+import org.alfresco.service.cmr.version.VersionHistory;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.GUID;
+
+
+/**
+ * Recordable version history integration tests.
+ *
+ * @author Roy Wetherall
+ * @since 2.3.1
+ */
+public class DeleteRecordVersionTest extends RecordableVersionsBaseTest
+{
+ /**
+ * Given that a document is created
+ * And the initial version is record
+ * When I delete the version record
+ * Then the version is deleted
+ * And the version history is not deleted
+ *
+ * @see https://issues.alfresco.com/jira/browse/RM-2562
+ */
+ public void testDeleteFirstRecordedVersion()
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ private NodeRef myDocument;
+
+ public void given() throws Exception
+ {
+ // create a document
+ myDocument = fileFolderService.create(dmFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
+
+ // make versionable
+ Map props = new HashMap(2);
+ props.put(RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY, RecordableVersionPolicy.ALL);
+ props.put(RecordableVersionModel.PROP_FILE_PLAN, filePlan);
+ nodeService.addAspect(myDocument, RecordableVersionModel.ASPECT_VERSIONABLE, props);
+ nodeService.addAspect(myDocument, ContentModel.ASPECT_VERSIONABLE, null);
+ }
+
+ public void when()
+ {
+ // check the initial version label
+ assertEquals("1.0", nodeService.getProperty(myDocument, ContentModel.PROP_VERSION_LABEL));
+
+ // check that the version history contains a single version that is recorded
+ VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
+ assertNotNull(versionHistory);
+ assertEquals(1, versionHistory.getAllVersions().size());
+
+ // check the recorded version is not marked as destroyed
+ Version head = versionHistory.getHeadVersion();
+ assertNotNull(head);
+ assertFalse(recordableVersionService.isRecordedVersionDestroyed(head));
+
+ // check the version record
+ NodeRef record = recordableVersionService.getVersionRecord(head);
+ assertTrue(recordService.isRecord(record));
+
+ // record should not have a version history because it is immutable
+ assertFalse(nodeService.hasAspect(record, ContentModel.ASPECT_VERSIONABLE));
+ VersionHistory recordVersionHistory = versionService.getVersionHistory(record);
+ assertNull(recordVersionHistory);
+
+ // destroy record
+ nodeService.deleteNode(record);
+ }
+
+ public void then()
+ {
+ // document is still versionable
+ assertTrue(nodeService.hasAspect(myDocument, ContentModel.ASPECT_VERSIONABLE));
+
+ // check the initial version label
+ assertEquals("1.0", nodeService.getProperty(myDocument, ContentModel.PROP_VERSION_LABEL));
+
+ // still has a version history, but the version is marked as destroyed
+ VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
+ assertNotNull(versionHistory);
+ assertEquals(1, versionHistory.getAllVersions().size());
+
+ // check the recorded version is marked as destroyed and the record version is not longer available
+ Version version = versionHistory.getHeadVersion();
+ assertNotNull(version);
+ assertTrue(recordableVersionService.isRecordedVersionDestroyed(version));
+ assertNull(recordableVersionService.getVersionRecord(version));
+ }
+ });
+ }
+
+ /**
+ * Given that a document is created
+ * And the initial version is record
+ * And the associated version record is deleted
+ * When a new version is created
+ * Then a new associated version record is created
+ * And the version is 1.1 (not 1.0 since this was deleted, but the version history maintained)
+ *
+ * @see https://issues.alfresco.com/jira/browse/RM-2562
+ */
+ public void testDeleteFirstRecordedVersionAndCreateNewVersion()
+ {
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ private NodeRef myDocument;
+
+ public void given() throws Exception
+ {
+ // create a document
+ myDocument = fileFolderService.create(dmFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
+ ContentWriter writer = fileFolderService.getWriter(myDocument);
+ writer.setEncoding("UTF-8");
+ writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
+ writer.putContent(GUID.generate());
+
+ // make versionable
+ Map props = new HashMap(2);
+ props.put(RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY, RecordableVersionPolicy.ALL);
+ props.put(RecordableVersionModel.PROP_FILE_PLAN, filePlan);
+ nodeService.addAspect(myDocument, RecordableVersionModel.ASPECT_VERSIONABLE, props);
+ nodeService.addAspect(myDocument, ContentModel.ASPECT_VERSIONABLE, null);
+ }
+
+ public void when()
+ {
+ // get the created version record
+ VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
+ Version head = versionHistory.getHeadVersion();
+ NodeRef record = recordableVersionService.getVersionRecord(head);
+
+ // destroy record
+ nodeService.deleteNode(record);
+
+ // update the content to create a new version (and version record)
+ ContentWriter writer = fileFolderService.getWriter(myDocument);
+ writer.putContent(GUID.generate());
+ }
+
+ public void then()
+ {
+ // document is still versionable
+ assertTrue(nodeService.hasAspect(myDocument, ContentModel.ASPECT_VERSIONABLE));
+
+ // check the version number has been incremented
+ assertEquals("1.1", nodeService.getProperty(myDocument, ContentModel.PROP_VERSION_LABEL));
+
+ // still has a version history, with 2 enties
+ VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
+ assertNotNull(versionHistory);
+ assertEquals(2, versionHistory.getAllVersions().size());
+
+ // latest version is current
+ Version head = versionHistory.getHeadVersion();
+ assertFalse(recordableVersionService.isRecordedVersionDestroyed(head));
+ assertNotNull(recordableVersionService.getVersionRecord(head));
+
+ // first version is destroyed
+ Version destroyed = versionHistory.getPredecessor(head);
+ assertTrue(recordableVersionService.isRecordedVersionDestroyed(destroyed));
+ assertNull(recordableVersionService.getVersionRecord(destroyed));
+
+ // get the version record for the current version
+ NodeRef versionRecord = recordableVersionService.getVersionRecord(head);
+ assertNotNull(versionRecord);
+ assertTrue(nodeService.exists(versionRecord));
+
+ Set from = relationshipService.getRelationshipsFrom(versionRecord);
+ assertTrue(from.isEmpty());
+
+ Set to = relationshipService.getRelationshipsTo(versionRecord);
+ assertTrue(to.isEmpty());
+ }
+ });
+ }
+
+ /**
+ * Given a chain of version records (1.0, 1.1, 1.2) which are all related
+ * When I delete version record 1.0
+ * Then 1.1 is the oldest version
+ */
+ public void testDeleteOldestVersion()
+ {
+ final NodeRef myDocument = createDocumentWithRecordVersions();
+
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ private VersionHistory versionHistory;
+
+ public void given() throws Exception
+ {
+ // get version history
+ versionHistory = versionService.getVersionHistory(myDocument);
+ }
+
+ public void when()
+ {
+ Version version10 = versionHistory.getVersion("1.0");
+ NodeRef recordVersion10 = recordableVersionService.getVersionRecord(version10);
+
+ // delete record version 1.0
+ nodeService.deleteNode(recordVersion10);
+ }
+
+ public void then()
+ {
+ // check the deleted version
+ Version version10 = versionHistory.getVersion("1.0");
+ assertNotNull(version10);
+ assertTrue(recordableVersionService.isRecordedVersionDestroyed(version10));
+ NodeRef recordVersion10 = recordableVersionService.getVersionRecord(version10);
+ assertNull(recordVersion10);
+
+ // verify 1.2 setup as expected
+ Version version12 = versionHistory.getHeadVersion();
+ assertEquals("1.2", version12.getVersionLabel());
+ NodeRef recordVersion12 = recordableVersionService.getVersionRecord(version12);
+ assertNotNull(recordVersion12);
+
+ assertTrue(relationshipService.getRelationshipsTo(recordVersion12, RelationshipService.RELATIONSHIP_VERSIONS).isEmpty());
+
+ Set from12 = relationshipService.getRelationshipsFrom(recordVersion12, RelationshipService.RELATIONSHIP_VERSIONS);
+ assertEquals(1, from12.size());
+
+ // verify 1.1 setup as expected
+ Version version11 = versionHistory.getPredecessor(version12);
+ assertEquals("1.1", version11.getVersionLabel());
+ NodeRef recordVersion11 = recordableVersionService.getVersionRecord(version11);
+ assertNotNull(recordVersion11);
+
+ Set to11 = relationshipService.getRelationshipsTo(recordVersion11, RelationshipService.RELATIONSHIP_VERSIONS);
+ assertEquals(1, to11.size());
+ assertEquals(recordVersion12, to11.iterator().next().getSource());
+
+ assertTrue(relationshipService.getRelationshipsFrom(recordVersion11, RelationshipService.RELATIONSHIP_VERSIONS).isEmpty());
+ }
+ });
+ }
+
+ /**
+ * Given a chain of version records (1.0, 1.1, 1.2) which are all related
+ * When I delete version record 1.1
+ * Then 1.2 now 'versions' 1.0
+ */
+ public void testDeleteMiddleVersion()
+ {
+ final NodeRef myDocument = createDocumentWithRecordVersions();
+
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ private VersionHistory versionHistory;
+
+ public void given() throws Exception
+ {
+ // get version history
+ versionHistory = versionService.getVersionHistory(myDocument);
+ }
+
+ public void when()
+ {
+ Version version11 = versionHistory.getVersion("1.1");
+ NodeRef recordVersion11 = recordableVersionService.getVersionRecord(version11);
+
+ // delete record version 1.1
+ nodeService.deleteNode(recordVersion11);
+ }
+
+ public void then()
+ {
+ // check the deleted version
+ Version version11 = versionHistory.getVersion("1.1");
+ assertNotNull(version11);
+ assertTrue(recordableVersionService.isRecordedVersionDestroyed(version11));
+ NodeRef recordVersion11 = recordableVersionService.getVersionRecord(version11);
+ assertNull(recordVersion11);
+
+ // verify 1.2 setup as expected
+ Version version12 = versionHistory.getHeadVersion();
+ assertEquals("1.2", version12.getVersionLabel());
+ NodeRef recordVersion12 = recordableVersionService.getVersionRecord(version12);
+ assertNotNull(recordVersion12);
+
+ assertTrue(relationshipService.getRelationshipsTo(recordVersion12, RelationshipService.RELATIONSHIP_VERSIONS).isEmpty());
+
+ Set from12 = relationshipService.getRelationshipsFrom(recordVersion12, RelationshipService.RELATIONSHIP_VERSIONS);
+ assertEquals(1, from12.size());
+
+ // verify 1.0 setup as expected
+ Version version10 = versionHistory.getVersion("1.0");
+ assertEquals("1.0", version10.getVersionLabel());
+ NodeRef recordVersion10 = recordableVersionService.getVersionRecord(version10);
+ assertNotNull(recordVersion10);
+
+ Set to10 = relationshipService.getRelationshipsTo(recordVersion10, RelationshipService.RELATIONSHIP_VERSIONS);
+ assertEquals(1, to10.size());
+ assertEquals(recordVersion12, to10.iterator().next().getSource());
+
+ assertTrue(relationshipService.getRelationshipsFrom(recordVersion10, RelationshipService.RELATIONSHIP_VERSIONS).isEmpty());
+
+ }
+ });
+ }
+
+ /**
+ * Given a chain of version records (1.0, 1.1, 1.2) which are all related
+ * When I delete version record 1.2
+ * Then 1.1 is the most recent version
+ */
+ public void testDeleteLatestVersion()
+ {
+ final NodeRef myDocument = createDocumentWithRecordVersions();
+
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ private VersionHistory versionHistory;
+
+ public void given() throws Exception
+ {
+ // get version history
+ versionHistory = versionService.getVersionHistory(myDocument);
+ }
+
+ public void when()
+ {
+ Version version10 = versionHistory.getVersion("1.0");
+ NodeRef recordVersion10 = recordableVersionService.getVersionRecord(version10);
+
+ // delete record version 1.0
+ nodeService.deleteNode(recordVersion10);
+ }
+
+ public void then()
+ {
+ // check the deleted version
+ Version version10 = versionHistory.getVersion("1.0");
+ assertNotNull(version10);
+ assertTrue(recordableVersionService.isRecordedVersionDestroyed(version10));
+ NodeRef recordVersion10 = recordableVersionService.getVersionRecord(version10);
+ assertNull(recordVersion10);
+
+ // verify 1.2 setup as expected
+ Version version12 = versionHistory.getHeadVersion();
+ assertEquals("1.2", version12.getVersionLabel());
+ NodeRef recordVersion12 = recordableVersionService.getVersionRecord(version12);
+ assertNotNull(recordVersion12);
+
+ assertTrue(relationshipService.getRelationshipsTo(recordVersion12, RelationshipService.RELATIONSHIP_VERSIONS).isEmpty());
+
+ Set from12 = relationshipService.getRelationshipsFrom(recordVersion12, RelationshipService.RELATIONSHIP_VERSIONS);
+ assertEquals(1, from12.size());
+
+ // verify 1.1 setup as expected
+ Version version11 = versionHistory.getPredecessor(version12);
+ assertEquals("1.1", version11.getVersionLabel());
+ NodeRef recordVersion11 = recordableVersionService.getVersionRecord(version11);
+ assertNotNull(recordVersion11);
+
+ Set to11 = relationshipService.getRelationshipsTo(recordVersion11, RelationshipService.RELATIONSHIP_VERSIONS);
+ assertEquals(1, to11.size());
+ assertEquals(recordVersion12, to11.iterator().next().getSource());
+
+ assertTrue(relationshipService.getRelationshipsFrom(recordVersion11, RelationshipService.RELATIONSHIP_VERSIONS).isEmpty());
+ }
+ });
+ }
+
+ /**
+ * Given that a version record
+ * When the version record is destroyed whilst retaining the meta data
+ * Then the version is marked as destroyed in the collab version history
+ */
+ public void testDetroyVerionRecordWithMetadata()
+ {
+ final NodeRef myDocument = createDocumentWithRecordVersions();
+
+ doBehaviourDrivenTest(new BehaviourDrivenTest()
+ {
+ private VersionHistory versionHistory;
+ private NodeRef recordVersion11;
+
+ public void given() throws Exception
+ {
+ // create file plan structure
+ NodeRef myCategory = filePlanService.createRecordCategory(filePlan, GUID.generate());
+ utils.createBasicDispositionSchedule(myCategory, GUID.generate(), GUID.generate(), true, true);
+
+ NodeRef myRecordFolder = recordFolderService.createRecordFolder(myCategory, GUID.generate());
+
+ // get version history
+ versionHistory = versionService.getVersionHistory(myDocument);
+
+ // file and complete all the version records into my record folder
+ for (Version version : versionHistory.getAllVersions())
+ {
+ NodeRef record = recordableVersionService.getVersionRecord(version);
+ fileFolderService.move(record, myRecordFolder, null);
+ utils.completeRecord(record);
+ }
+ }
+
+ public void when()
+ {
+ Version version11 = versionHistory.getVersion("1.1");
+ recordVersion11 = recordableVersionService.getVersionRecord(version11);
+
+ Map params = new HashMap(1);
+ params.put(CompleteEventAction.PARAM_EVENT_NAME, CommonRMTestUtils.DEFAULT_EVENT_NAME);
+ rmActionService.executeRecordsManagementAction(recordVersion11, CompleteEventAction.NAME, params);
+
+ rmActionService.executeRecordsManagementAction(recordVersion11, CutOffAction.NAME);
+
+ rmActionService.executeRecordsManagementAction(recordVersion11, DestroyAction.NAME);
+ }
+
+ public void then()
+ {
+ // verify that the version history looks as expected
+ VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
+ assertNotNull(versionHistory);
+ Collection versions = versionHistory.getAllVersions();
+ assertEquals(3, versions.size());
+
+ // verify 1.2 setup as expected
+ Version version12 = versionHistory.getHeadVersion();
+ assertEquals("1.2", version12.getVersionLabel());
+ assertFalse(recordableVersionService.isRecordedVersionDestroyed(version12));
+ NodeRef recordVersion12 = recordableVersionService.getVersionRecord(version12);
+ assertNotNull(recordVersion12);
+ assertFalse(recordService.isMetadataStub(recordVersion12));
+
+ assertTrue(relationshipService.getRelationshipsTo(recordVersion12, "versions").isEmpty());
+
+ Set from12 = relationshipService.getRelationshipsFrom(recordVersion12, "versions");
+ assertEquals(1, from12.size());
+
+ // verify 1.1 setup as expected
+ Version version11 = versionHistory.getPredecessor(version12);
+ assertEquals("1.1", version11.getVersionLabel());
+ assertTrue(recordableVersionService.isRecordedVersionDestroyed(version11));
+ assertNotNull(recordVersion11);
+ assertTrue(recordService.isMetadataStub(recordVersion11));
+
+ Set to11 = relationshipService.getRelationshipsTo(recordVersion11, "versions");
+ assertEquals(1, to11.size());
+ assertEquals(recordVersion12, to11.iterator().next().getSource());
+
+ Set from11 = relationshipService.getRelationshipsFrom(recordVersion11, "versions");
+ assertEquals(1, from11.size());
+
+ // verify 1.0 setup as expected
+ Version version10 = versionHistory.getPredecessor(version11);
+ assertEquals("1.0", version10.getVersionLabel());
+ assertFalse(recordableVersionService.isRecordedVersionDestroyed(version10));
+ NodeRef recordVersion10 = recordableVersionService.getVersionRecord(version10);
+ assertNotNull(recordVersion10);
+ assertFalse(recordService.isMetadataStub(recordVersion10));
+
+ Set to10 = relationshipService.getRelationshipsTo(recordVersion10, "versions");
+ assertEquals(1, to10.size());
+ assertEquals(recordVersion11, to10.iterator().next().getSource());
+
+ assertTrue(relationshipService.getRelationshipsFrom(recordVersion10, "versions").isEmpty());
+
+ }
+ });
+ }
+}
diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/RecordableVersionsBaseTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/RecordableVersionsBaseTest.java
index 767f3d2ec8..32f1269bf3 100644
--- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/RecordableVersionsBaseTest.java
+++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/version/RecordableVersionsBaseTest.java
@@ -19,15 +19,18 @@
package org.alfresco.module.org_alfresco_module_rm.test.integration.version;
import java.io.Serializable;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.relationship.Relationship;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
-import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl;
+import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionPolicy;
+import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -35,9 +38,12 @@ import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
+import org.alfresco.util.GUID;
import org.alfresco.util.PropertyMap;
/**
+ * Recordable versions base integration test
+ *
* @author Roy Wetherall
* @since 2.3
*/
@@ -54,7 +60,16 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
protected static final String CONTENT =
"Simple + Smart. A smarter way to build, a smarter way to deploy. Its simple because we focus on the end "
+ "user and smart because we support more open standards than any other ECM platform, while delivering all "
- + "the value a traditional platform provides.";
+ + "the value a traditional platform provides.";
+
+ protected RecordableVersionService recordableVersionService;
+
+ @Override
+ protected void initServices()
+ {
+ super.initServices();
+ recordableVersionService = (RecordableVersionService)applicationContext.getBean("RecordableVersionService");
+ }
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#isCollaborationSiteTest()
@@ -76,25 +91,31 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
// create authentication for owner
createPerson(OWNER);
+ // prepare content
+ prepareContent(dmDocument);
+ }
+
+ protected void prepareContent(NodeRef content)
+ {
// add titled aspect
PropertyMap titledProperties = new PropertyMap(2);
titledProperties.put(ContentModel.PROP_TITLE, "document title");
titledProperties.put(ContentModel.PROP_DESCRIPTION, "document description");
- nodeService.addAspect(dmDocument, ContentModel.ASPECT_TITLED, titledProperties);
+ nodeService.addAspect(content, ContentModel.ASPECT_TITLED, titledProperties);
// add ownable aspect
PropertyMap ownableProperties = new PropertyMap(1);
ownableProperties.put(ContentModel.PROP_OWNER, OWNER);
- nodeService.addAspect(dmDocument, ContentModel.ASPECT_OWNABLE, ownableProperties);
+ nodeService.addAspect(content, ContentModel.ASPECT_OWNABLE, ownableProperties);
// add Dublin core aspect
PropertyMap dublinCoreProperties = new PropertyMap(2);
dublinCoreProperties.put(QNAME_PUBLISHER, PUBLISHER);
dublinCoreProperties.put(QNAME_SUBJECT, SUBJECT);
- nodeService.addAspect(dmDocument, ContentModel.ASPECT_DUBLINCORE, dublinCoreProperties);
+ nodeService.addAspect(content, ContentModel.ASPECT_DUBLINCORE, dublinCoreProperties);
// add content
- ContentWriter writer = contentService.getWriter(dmDocument, ContentModel.PROP_CONTENT, true);
+ ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true);
writer.setEncoding("UTF-8");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent(CONTENT);
@@ -122,7 +143,7 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
// store document state
Map beforeProperties = nodeService.getProperties(document);
- Set beforeAspects = nodeService.getAspects(dmDocument);
+ Set beforeAspects = nodeService.getAspects(document);
// get the current version
Version version = versionService.getCurrentVersion(document);
@@ -144,7 +165,7 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
checkAspects(frozen, beforeAspects);
// record version node reference is available on version
- NodeRef record = (NodeRef)version.getVersionProperties().get(RecordableVersionServiceImpl.PROP_VERSION_RECORD);
+ NodeRef record = recordableVersionService.getVersionRecord(version);
assertNotNull(record);
// check that the version record information has been added
@@ -185,7 +206,7 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
assertEquals(versionLabel, version.getVersionLabel());
// record version node reference is available on version
- NodeRef record = (NodeRef)version.getVersionProperties().get(RecordableVersionServiceImpl.PROP_VERSION_RECORD);
+ NodeRef record = recordableVersionService.getVersionRecord(version);
assertNull(record);
// check the version history
@@ -230,6 +251,9 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
}
}
+ // remove "owner" from cloneFrozenProperties
+ cloneFrozenProperties.remove(ContentModel.PROP_OWNER);
+
// frozen properties should be empty
assertTrue("Properties in frozen state, but not in origional. " + cloneFrozenProperties.keySet(), cloneFrozenProperties.isEmpty());
@@ -258,5 +282,121 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
fail("Aspects in the frozen state, but not in origional. " + frozenAspects.toString());
}
}
+
+ /**
+ * Creates a document with three versions (1.0, 1.1, 1.2) all of which
+ * are recorded.
+ *
+ * @return NodeRef node reference
+ */
+ protected NodeRef createDocumentWithRecordVersions()
+ {
+ // create document and initial version (1.0)
+ final NodeRef myDocument = doTestInTransaction(new Test()
+ {
+ @Override
+ public NodeRef run() throws Exception
+ {
+ // create a document
+ NodeRef testDoc = fileFolderService.create(dmFolder, GUID.generate(), ContentModel.TYPE_CONTENT).getNodeRef();
+ ContentWriter writer = fileFolderService.getWriter(testDoc);
+ writer.setEncoding("UTF-8");
+ writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
+ writer.putContent(GUID.generate());
+
+ // make versionable
+ Map props = new HashMap(2);
+ props.put(RecordableVersionModel.PROP_RECORDABLE_VERSION_POLICY, RecordableVersionPolicy.ALL);
+ props.put(RecordableVersionModel.PROP_FILE_PLAN, filePlan);
+ nodeService.addAspect(testDoc, RecordableVersionModel.ASPECT_VERSIONABLE, props);
+ nodeService.addAspect(testDoc, ContentModel.ASPECT_VERSIONABLE, null);
+
+ return testDoc;
+ }
+ });
+
+ // create 1.1
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run() throws Exception
+ {
+ // update content
+ ContentWriter writer = fileFolderService.getWriter(myDocument);
+ writer.putContent(GUID.generate());
+
+ return null;
+ }
+ });
+
+ // create 1.2
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run() throws Exception
+ {
+ // update content
+ ContentWriter writer = fileFolderService.getWriter(myDocument);
+ writer.putContent(GUID.generate());
+
+ return null;
+ }
+ });
+
+ // we do these checks to ensure that the test data is in the correct state before we
+ // start to manipulate the versions and execute tests
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run() throws Exception
+ {
+ // verify that the version history looks as expected
+ VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
+ assertNotNull(versionHistory);
+ Collection versions = versionHistory.getAllVersions();
+ assertEquals(3, versions.size());
+
+ // verify 1.2 setup as expected
+ Version version12 = versionHistory.getHeadVersion();
+ assertEquals("1.2", version12.getVersionLabel());
+ NodeRef recordVersion12 = recordableVersionService.getVersionRecord(version12);
+ assertNotNull(recordVersion12);
+
+ assertTrue(relationshipService.getRelationshipsTo(recordVersion12, "versions").isEmpty());
+
+ Set from12 = relationshipService.getRelationshipsFrom(recordVersion12, "versions");
+ assertEquals(1, from12.size());
+
+ // verify 1.1 setup as expected
+ Version version11 = versionHistory.getPredecessor(version12);
+ assertEquals("1.1", version11.getVersionLabel());
+ NodeRef recordVersion11 = recordableVersionService.getVersionRecord(version11);
+ assertNotNull(recordVersion11);
+
+ Set to11 = relationshipService.getRelationshipsTo(recordVersion11, "versions");
+ assertEquals(1, to11.size());
+ assertEquals(recordVersion12, to11.iterator().next().getSource());
+
+ Set from11 = relationshipService.getRelationshipsFrom(recordVersion11, "versions");
+ assertEquals(1, from11.size());
+
+ // verify 1.0 setup as expected
+ Version version10 = versionHistory.getPredecessor(version11);
+ assertEquals("1.0", version10.getVersionLabel());
+ NodeRef recordVersion10 = recordableVersionService.getVersionRecord(version10);
+ assertNotNull(recordVersion10);
+
+ Set to10 = relationshipService.getRelationshipsTo(recordVersion10, "versions");
+ assertEquals(1, to10.size());
+ assertEquals(recordVersion11, to10.iterator().next().getSource());
+
+ assertTrue(relationshipService.getRelationshipsFrom(recordVersion10, "versions").isEmpty());
+
+ return null;
+ }
+ });
+
+ return myDocument;
+ }
}
diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspectUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspectUnitTest.java
new file mode 100644
index 0000000000..8069678d65
--- /dev/null
+++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/VersionRecordAspectUnitTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService;
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
+import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.version.Version;
+import org.alfresco.service.cmr.version.VersionHistory;
+import org.alfresco.service.cmr.version.VersionService;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+/**
+ * Version record aspect unit tests
+ *
+ * @author Roy Wetherall
+ * @since 2.3.1
+ */
+public class VersionRecordAspectUnitTest extends BaseUnitTest
+{
+ /** service mocks */
+ private @Mock VersionHistory mockedVersionHistory;
+ private @Mock Version mockedVersion;
+ private @Mock VersionService mockedVersionService;
+ private @Mock RelationshipService mockedRelationshipService;
+
+ /** test object */
+ private @InjectMocks VersionRecordAspect versionRecordAspect;
+
+ /**
+ * given that there is no recorded version
+ * before delete of record
+ * then nothing happens
+ */
+ @Test
+ public void beforeDeleteNoVersionNodeRef()
+ {
+ NodeRef nodeRef = generateNodeRef();
+
+ when(mockedRecordableVersionService.getRecordedVersion(nodeRef))
+ .thenReturn(null);
+
+ versionRecordAspect.beforeDeleteNode(nodeRef);
+
+ verify(mockedNodeService, never()).getProperty(nodeRef, RecordableVersionModel.PROP_VERSION_LABEL);
+ verify(mockedRecordableVersionService, never()).destroyRecordedVersion(any(Version.class));
+ }
+
+ /**
+ * given that there is a recorded version
+ * before delete of record
+ * then the version is marked as destroyed
+ */
+ @Test
+ public void beforeDeleteMarkVersionDestroyed()
+ {
+ NodeRef nodeRef = generateNodeRef();
+
+ when(mockedRecordableVersionService.getRecordedVersion(nodeRef))
+ .thenReturn(mockedVersion);
+
+ versionRecordAspect.beforeDeleteNode(nodeRef);
+
+ verify(mockedRecordableVersionService).destroyRecordedVersion(mockedVersion);
+ }
+}
diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImplUnitTest.java
index 21d590dd27..19dd235cae 100644
--- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImplUnitTest.java
+++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/version/RecordableVersionServiceImplUnitTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2014 Alfresco Software Limited.
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -18,6 +18,8 @@
*/
package org.alfresco.module.org_alfresco_module_rm.version;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
@@ -27,6 +29,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.util.Collections;
@@ -419,9 +422,16 @@ public class RecordableVersionServiceImplUnitTest extends BaseUnitTest
{
// latest version is already recorded
Version mockedVersion = mock(VersionImpl.class);
- doReturn(Collections.singletonMap(RecordableVersionServiceImpl.PROP_VERSION_RECORD, generateNodeRef())).when(mockedVersion).getVersionProperties();
- doReturn(true).when(mockedNodeService).hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE);
- doReturn(mockedVersion).when(recordableVersionService).getCurrentVersion(nodeRef);
+ NodeRef versionNodeRef = generateNodeRef();
+ when(mockedVersion.getFrozenStateNodeRef())
+ .thenReturn(versionNodeRef);
+
+ when(mockedNodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))
+ .thenReturn(true);
+ when(mockedDbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
+ .thenReturn(true);
+ doReturn(mockedVersion)
+ .when(recordableVersionService).getCurrentVersion(nodeRef);
// create record from version
recordableVersionService.createRecordFromLatestVersion(filePlan, nodeRef);
@@ -495,4 +505,157 @@ public class RecordableVersionServiceImplUnitTest extends BaseUnitTest
RecordableVersionModel.ASPECT_RECORDED_VERSION,
Collections.singletonMap(RecordableVersionModel.PROP_RECORD_NODE_REF, (Serializable)newRecordNodeRef));
}
+
+
+ /**
+ * given the destroyed prop isn't set
+ * when I ask if the version is destroyed
+ * then the result is false
+ */
+ @Test
+ public void propNotSetVersionNotDestroyed()
+ {
+ // set up version
+ Version mockedVersion = mock(VersionImpl.class);
+ NodeRef versionNodeRef = generateNodeRef();
+ when(mockedVersion.getFrozenStateNodeRef())
+ .thenReturn(versionNodeRef);
+
+ // set prop not set
+ when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED))
+ .thenReturn(null);
+
+ // is version destroyed
+ assertFalse(recordableVersionService.isRecordedVersionDestroyed(mockedVersion));
+ }
+
+ /**
+ * given the destroyed prop is set
+ * when I ask if the version is destroyed
+ * then the result matches the value set in the destroy property
+ */
+ @Test
+ public void propSetVersionDestroyed()
+ {
+ // set up version
+ Version mockedVersion = mock(VersionImpl.class);
+ NodeRef versionNodeRef = generateNodeRef();
+ when(mockedVersion.getFrozenStateNodeRef())
+ .thenReturn(versionNodeRef);
+
+ // set prop
+ when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED))
+ .thenReturn(Boolean.TRUE);
+
+ // is version destroyed
+ assertTrue(recordableVersionService.isRecordedVersionDestroyed(mockedVersion));
+
+ // set prop
+ when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED))
+ .thenReturn(Boolean.FALSE);
+
+ // is version destroyed
+ assertFalse(recordableVersionService.isRecordedVersionDestroyed(mockedVersion));
+ }
+
+ /**
+ * given that the version node doesn't have the recorded version aspect applied
+ * when I mark the version as destroyed
+ * then nothing happens
+ */
+ @Test
+ public void noAspectMarkAsDestroyed()
+ {
+ // set up version
+ Version mockedVersion = mock(VersionImpl.class);
+ NodeRef versionNodeRef = generateNodeRef();
+ when(mockedVersion.getFrozenStateNodeRef())
+ .thenReturn(versionNodeRef);
+
+ // indicate that the version doesn't have the aspect
+ when(mockedDbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
+ .thenReturn(false);
+
+ // mark as destroyed
+ recordableVersionService.destroyRecordedVersion(mockedVersion);
+
+ // verify nothing happened
+ verify(mockedDbNodeService, never())
+ .setProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED, Boolean.TRUE);
+ }
+
+ /**
+ * given that the version node ref has the recorded version aspect applied
+ * and the record version reference exists
+ * when I mark the version as destroyed
+ * then the version is marked as destroyed
+ */
+ @Test
+ public void markAsDestroyed()
+ {
+ // set up version
+ Version mockedVersion = mock(VersionImpl.class);
+ NodeRef versionNodeRef = generateNodeRef();
+ NodeRef versionRecordNodeRef = generateNodeRef();
+ when(mockedVersion.getFrozenStateNodeRef())
+ .thenReturn(versionNodeRef);
+ when(mockedDbNodeService.exists(versionRecordNodeRef))
+ .thenReturn(true);
+
+ // indicate that the version doesn't have the aspect
+ when(mockedDbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
+ .thenReturn(true);
+
+ // indicate that the associated version record exists
+ when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF))
+ .thenReturn(versionRecordNodeRef);
+
+ // mark as destroyed
+ recordableVersionService.destroyRecordedVersion(mockedVersion);
+
+ // verify that the version was marked as destroyed
+ verify(mockedDbNodeService)
+ .setProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED, Boolean.TRUE);
+ // and the reference to the version record was cleared
+ verify(mockedDbNodeService)
+ .setProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF, null);
+ }
+
+ /**
+ * given that the version node ref has the recorded version aspect applied
+ * and the associated version record has been deleted
+ * when I mark the version as destroyed
+ * then the version is marked as destroyed
+ * and the reference to the deleted version record is removed
+ */
+ @Test
+ public void markAsDestroyedClearNodeRef()
+ {
+ // set up version
+ Version mockedVersion = mock(VersionImpl.class);
+ NodeRef versionNodeRef = generateNodeRef();
+ NodeRef versionRecordNodeRef = generateNodeRef();
+ when(mockedVersion.getFrozenStateNodeRef())
+ .thenReturn(versionNodeRef);
+ when(mockedDbNodeService.exists(versionRecordNodeRef))
+ .thenReturn(false);
+
+ // indicate that the version doesn't have the aspect
+ when(mockedDbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
+ .thenReturn(true);
+
+ // indicate that the associated version record exists
+ when(mockedDbNodeService.getProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF))
+ .thenReturn(versionRecordNodeRef);
+
+ // mark as destroyed
+ recordableVersionService.destroyRecordedVersion(mockedVersion);
+
+ // verify that the version was marked as destroyed
+ verify(mockedDbNodeService)
+ .setProperty(versionNodeRef, RecordableVersionModel.PROP_DESTROYED, Boolean.TRUE);
+ // and the reference to the version record was cleared
+ verify(mockedDbNodeService)
+ .setProperty(versionNodeRef, RecordableVersionModel.PROP_RECORD_NODE_REF, null);
+ }
}
\ No newline at end of file