Merged BRANCHES/V2.3 to HEAD:

118277: RM-2194: unit tests used to demonstrate current behaviour
   119284: RM-2562: Deleting records from versions produces inconsistent behaviour
   119506: RM-2562: Deleting record from versions produces inconsistent behaviour
   119692: Review RM-223 feedback


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@119819 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Tom Page
2015-12-09 12:03:40 +00:00
25 changed files with 1562 additions and 93 deletions

View File

@@ -94,6 +94,12 @@
<type>d:text</type>
<index enabled="false"/>
</property>
<!-- indicates whether the version record has been destroyed or not -->
<property name="rmv:destroyed">
<title>Destroyed</title>
<type>d:boolean</type>
<default>false</default>>
</property>
</properties>
</aspect>

View File

@@ -259,6 +259,7 @@
<bean id="destroy" class="org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction" parent="rmAction"
depends-on="rmDestroyRecordsScheduledForDestructionCapability">
<property name="capabilityService" ref="CapabilityService" />
<property name="recordableVersionService" ref="RecordableVersionService" />
<property name="contentDestructionComponent" ref="contentDestructionComponent"/>
<property name="ghostingEnabled">
<value>${rm.ghosting.enabled}</value>

View File

@@ -1060,6 +1060,7 @@
<property name="recordsManagementContainerType" ref="rma.recordsManagementContainer"/>
<property name="renditionService" ref="RenditionService" />
<property name="dispositionService" ref="DispositionService"/>
<property name="recordableVersionService" ref="RecordableVersionService"/>
</bean>
<bean id="recordMetadataAspectBootstrap" class="org.alfresco.module.org_alfresco_module_rm.record.RecordMetadataBootstrap" init-method="init" abstract="true">

View File

@@ -12,6 +12,12 @@
</property>
</bean>
<!-- Recordable version model behaviours -->
<bean id="rmv.versionRecord" class="org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.VersionRecordAspect" parent="rm.baseBehaviour">
<property name="recordableVersionService" ref="RecordableVersionService" />
<property name="relationshipService" ref="RelationshipService" />
</bean>
<!-- extended version service bean definition -->
<bean id="rm.versionService" abstract="true" class="org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionServiceImpl">
<property name="filePlanService" ref="FilePlanService" />
@@ -63,7 +69,11 @@
<![CDATA[
org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService.isCurrentVersionRecorded=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService.isRecordedVersion=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService.getVersionRecord=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService.getRecordedVersion=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService.createRecordFromLatestVersion=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService.isRecordedVersionDestroyed=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService.destroyRecordedVersion=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService.*=RM_DENY
]]>
</value>

View File

@@ -62,7 +62,7 @@ function main()
{
var nodeRef = args["nodeRef"],
node = search.findNode(nodeRef),
versionHistory, version, p, recordNodeRef;
versionHistory, version, p, recordNodeRef, isRecordedVersionDestroyed;
if (node != null)
{
@@ -73,11 +73,14 @@ function main()
{
version = versionHistory[i];
p = getPerson(version.creator);
recordNodeRef = version.getVersionProperty("recordNodeRef");
isRecordedVersionDestroyed = version.getVersionProperty("RecordedVersionDestroyed");
versions[versions.length] =
{
nodeRef: version.node.nodeRef.toString(),
name: version.node.name,
name: (isRecordedVersionDestroyed == true) ? "" : version.node.name,
label: version.label,
description: version.description,
createdDate: version.createdDate,
@@ -87,7 +90,8 @@ function main()
firstName: p.firstName,
lastName: p.lastName
},
recordNodeRef: recordNodeRef ? recordNodeRef.toString() : ""
recordNodeRef: recordNodeRef ? recordNodeRef.toString() : "",
isRecordedVersionDestroyed: isRecordedVersionDestroyed
};
}
}
@@ -107,7 +111,8 @@ function main()
firstName: p.firstName,
lastName: p.lastName
},
recordNodeRef: ""
recordNodeRef: "",
isRecordedVersionDestroyed: false
};
}
}

View File

@@ -14,7 +14,8 @@
"firstName": "${v.creator.firstName!""}",
"lastName": "${v.creator.lastName!""}"
},
"recordNodeRef": "${v.recordNodeRef}"
"recordNodeRef": "${v.recordNodeRef}",
"isRecordedVersionDestroyed": ${v.isRecordedVersionDestroyed?c}
}<#if (v_has_next)>,</#if>
</#list>
]

View File

@@ -27,9 +27,11 @@ import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.content.ContentDestructionComponent;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.namespace.QName;
import org.apache.commons.lang.StringUtils;
@@ -49,6 +51,9 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
/** Capability service */
private CapabilityService capabilityService;
/** Recordable version service */
private RecordableVersionService recordableVersionService;
/** Indicates if ghosting is enabled or not */
private boolean ghostingEnabled = true;
@@ -68,6 +73,14 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
this.capabilityService = capabilityService;
}
/**
* @param recordableVersionService recordable version service
*/
public void setRecordableVersionService(RecordableVersionService recordableVersionService)
{
this.recordableVersionService = recordableVersionService;
}
/**
* @param ghostingEnabled true if ghosting is enabled, false otherwise
*/
@@ -140,6 +153,13 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase
{
if (isGhostOnDestroySetForAction(action, record))
{
// mark version as destroyed
Version version = recordableVersionService.getRecordedVersion(record);
if (version != null)
{
recordableVersionService.destroyRecordedVersion(version);
}
// Add the ghosted aspect
getNodeService().addAspect(record, ASPECT_GHOSTED, null);

View File

@@ -36,7 +36,6 @@ import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -110,7 +109,7 @@ public class RecordAspect extends AbstractDisposableItem
)
public void onCreateChildAssociation(final ChildAssociationRef childAssocRef, boolean bNew)
{
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
authenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork()
@@ -173,7 +172,7 @@ public class RecordAspect extends AbstractDisposableItem
// Deal with versioned records
if (reference.equals(CUSTOM_REF_VERSIONS))
{
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
authenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork()
@@ -240,7 +239,7 @@ public class RecordAspect extends AbstractDisposableItem
isFilePlanComponent(oldChildAssocRef.getParentRef()))
{
final NodeRef record = newChildAssocRef.getChildRef();
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
authenticationUtil.runAs(new RunAsWork<Object>()
{
public Object doWork()
{
@@ -256,7 +255,7 @@ public class RecordAspect extends AbstractDisposableItem
return null;
}
}, AuthenticationUtil.getAdminUserName());
}, authenticationUtil.getAdminUserName());
}
}

View File

@@ -0,0 +1,123 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
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.version.RecordableVersionService;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
/**
* rmv:versionRecord behaviour bean
*
* @author Roy Wetherall
* @since 2.3.1
*/
@BehaviourBean
(
defaultType = "rmv:versionRecord"
)
public class VersionRecordAspect extends BaseBehaviourBean
implements NodeServicePolicies.BeforeDeleteNodePolicy
{
/** recordable version service */
private RecordableVersionService recordableVersionService;
/** relationship service */
private RelationshipService relationshipService;
/**
* @param recordableVersionService recordable version service
*/
public void setRecordableVersionService(RecordableVersionService recordableVersionService)
{
this.recordableVersionService = recordableVersionService;
}
/**
* @param relationshipService relationship service
*/
public void setRelationshipService(RelationshipService relationshipService)
{
this.relationshipService = relationshipService;
}
/**
* If the record is a version record then delete the associated version entry
*
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
@Behaviour (kind = BehaviourKind.CLASS)
public void beforeDeleteNode(final NodeRef nodeRef)
{
final Version version = recordableVersionService.getRecordedVersion(nodeRef);
if (version != null)
{
authenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork()
{
behaviourFilter.disableBehaviour();
try
{
// mark the associated version as destroyed
recordableVersionService.destroyRecordedVersion(version);
// re-organise the versions relationships ...
// if there is only one "to" reference since a version can only have one predecessor
Set<Relationship> tos = relationshipService.getRelationshipsTo(nodeRef, RelationshipService.RELATIONSHIP_VERSIONS);
if (!tos.isEmpty() && tos.size() == 1)
{
// if there is some "from" references
Set<Relationship> froms = relationshipService.getRelationshipsFrom(nodeRef, RelationshipService.RELATIONSHIP_VERSIONS);
if (!froms.isEmpty())
{
// get predecessor version relationship
Relationship to = tos.iterator().next();
for (Relationship from : froms)
{
// point the "to" the all the "from's"
relationshipService.addRelationship(RelationshipService.RELATIONSHIP_VERSIONS, to.getSource(), from.getTarget());
}
}
}
}
finally
{
behaviourFilter.enableBehaviour();
}
return null;
}
});
}
}
}

View File

@@ -19,9 +19,6 @@
package org.alfresco.module.org_alfresco_module_rm.record;
import static com.google.common.collect.Lists.newArrayList;
import static org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel.PROP_VERSIONED_NODEREF;
import static org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionModel.PROP_VERSION_LABEL;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import java.io.Serializable;
import java.util.ArrayList;
@@ -62,7 +59,7 @@ import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.role.Role;
import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService;
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.RecordableVersionService;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.ClassPolicyDelegate;
@@ -123,8 +120,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
NodeServicePolicies.OnCreateChildAssociationPolicy,
NodeServicePolicies.OnAddAspectPolicy,
NodeServicePolicies.OnRemoveAspectPolicy,
NodeServicePolicies.OnUpdatePropertiesPolicy,
NodeServicePolicies.BeforeDeleteNodePolicy
NodeServicePolicies.OnUpdatePropertiesPolicy
{
/** Logger */
private static Log logger = LogFactory.getLog(RecordServiceImpl.class);
@@ -233,6 +229,9 @@ public class RecordServiceImpl extends BaseBehaviourBean
/** records management container type */
private RecordsManagementContainerType recordsManagementContainerType;
/** recordable version service */
private RecordableVersionService recordableVersionService;
/** list of available record meta-data aspects and the file plan types the are applicable to */
private Map<QName, Set<QName>> recordMetaDataAspects;
@@ -386,6 +385,14 @@ public class RecordServiceImpl extends BaseBehaviourBean
this.recordsManagementContainerType = recordsManagementContainerType;
}
/**
* @param recordableVersionService recordable version service
*/
public void setRecordableVersionService(RecordableVersionService recordableVersionService)
{
this.recordableVersionService = recordableVersionService;
}
/**
* Init method
*/
@@ -1035,6 +1042,18 @@ public class RecordServiceImpl extends BaseBehaviourBean
recordsManagementContainerType.enable();
}
// if versionable, then remove without destroying version history,
// because it is being shared with the originating document
behaviourFilter.disableBehaviour(ContentModel.ASPECT_VERSIONABLE);
try
{
nodeService.removeAspect(record, ContentModel.ASPECT_VERSIONABLE);
}
finally
{
behaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE);
}
// make record
makeRecord(record);
@@ -1092,7 +1111,7 @@ public class RecordServiceImpl extends BaseBehaviourBean
for (Version previousVersion : previousVersions)
{
// look for the associated record
final NodeRef previousRecord = (NodeRef)previousVersion.getVersionProperties().get(RecordableVersionServiceImpl.PROP_VERSION_RECORD);
final NodeRef previousRecord = recordableVersionService.getVersionRecord(previousVersion);
if (previousRecord != null)
{
versionRecord = previousRecord;
@@ -1820,37 +1839,4 @@ public class RecordServiceImpl extends BaseBehaviourBean
throw new RecordLinkRuntimeException("Can only unlink a record from a record folder.");
}
}
/**
* @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
@Behaviour
(
kind = BehaviourKind.CLASS,
type = "rma:record"
)
public void beforeDeleteNode(NodeRef nodeRef)
{
final NodeRef versionedNodeRef = (NodeRef) nodeService.getProperty(nodeRef, PROP_VERSIONED_NODEREF);
if (versionedNodeRef != null)
{
String versionLabel = (String) nodeService.getProperty(nodeRef, PROP_VERSION_LABEL);
if (isNotBlank(versionLabel))
{
final Version version = versionService.getVersionHistory(versionedNodeRef).getVersion(versionLabel);
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork()
{
versionService.deleteVersion(versionedNodeRef, version);
return null;
}
});
}
}
}
}

View File

@@ -21,6 +21,8 @@ package org.alfresco.module.org_alfresco_module_rm.relationship;
import static org.alfresco.util.ParameterCheck.mandatory;
import static org.alfresco.util.ParameterCheck.mandatoryString;
import java.io.Serializable;
import org.alfresco.service.cmr.repository.NodeRef;
/**
@@ -29,8 +31,11 @@ import org.alfresco.service.cmr.repository.NodeRef;
* @author Tuna Aksoy
* @since 2.3
*/
public class RelationshipImpl implements Relationship
public class RelationshipImpl implements Relationship, Serializable
{
/** serial UID */
private static final long serialVersionUID = 9120649510198344978L;
/** The unique name of the relationship */
private String uniqueName;
@@ -114,4 +119,39 @@ public class RelationshipImpl implements Relationship
{
this.target = target;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj instanceof Relationship)
{
RelationshipImpl that = (RelationshipImpl) obj;
return (this.uniqueName.equals(that.uniqueName)
&& this.source.equals(that.source)
&& this.target.equals(that.target));
}
else
{
return false;
}
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
int prime = 31;
int result = prime + uniqueName.hashCode();
result = (prime*result) + source.hashCode();
return (prime*result) + target.hashCode();
}
}

View File

@@ -30,6 +30,9 @@ import org.alfresco.service.cmr.repository.NodeRef;
*/
public interface RelationshipService
{
/** System relationship names */
static final String RELATIONSHIP_VERSIONS = "versions";
/**
* Gets all the existing relationship definitions
*
@@ -86,6 +89,20 @@ public interface RelationshipService
*/
Set<Relationship> getRelationshipsFrom(NodeRef nodeRef);
/**
* Gets all the relationships that come out from the given node reference
* that match the a given name filter.
* <p>
* Exact match only.
*
* @param nodeRef The node reference
* @param nameFilter Name filter for results
* @return All relationships that come out from the given node reference
*
* @since 2.3.1
*/
Set<Relationship> getRelationshipsFrom(NodeRef nodeRef, String nameFilter);
/**
* Gets all the relationships that go into the given node reference
*
@@ -94,6 +111,20 @@ public interface RelationshipService
*/
Set<Relationship> getRelationshipsTo(NodeRef nodeRef);
/**
* Gets all the relationships that go into the given node reference
* that match the a given name filter.
* <p>
* 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<Relationship> getRelationshipsTo(NodeRef nodeRef, String nameFilter);
/**
* Adds a relationship from the given node <code>source</code>
* to the give node <code>target</code> with the given unique name

View File

@@ -376,16 +376,25 @@ public class RelationshipServiceImpl extends RecordsManagementAdminBase implemen
*/
@Override
public Set<Relationship> 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<Relationship> getRelationshipsFrom(NodeRef nodeRef, String nameFilter)
{
mandatory("nodeRef", nodeRef);
Set<Relationship> relationships = new HashSet<Relationship>();
List<AssociationRef> customReferencesFrom = getNodeService().getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
relationships.addAll(generateRelationshipFromAssociationRef(customReferencesFrom));
relationships.addAll(generateRelationshipFromAssociationRef(customReferencesFrom, nameFilter));
List<ChildAssociationRef> customChildReferences = getNodeService().getChildAssocs(nodeRef);
relationships.addAll(generateRelationshipFromParentChildAssociationRef(customChildReferences));
relationships.addAll(generateRelationshipFromParentChildAssociationRef(customChildReferences, nameFilter));
return relationships;
}
@@ -395,16 +404,25 @@ public class RelationshipServiceImpl extends RecordsManagementAdminBase implemen
*/
@Override
public Set<Relationship> 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<Relationship> getRelationshipsTo(NodeRef nodeRef, String nameFilter)
{
mandatory("nodeRef", nodeRef);
Set<Relationship> relationships = new HashSet<Relationship>();
List<AssociationRef> customReferencesTo = getNodeService().getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
relationships.addAll(generateRelationshipFromAssociationRef(customReferencesTo));
relationships.addAll(generateRelationshipFromAssociationRef(customReferencesTo, nameFilter));
List<ChildAssociationRef> customParentReferences = getNodeService().getParentAssocs(nodeRef);
relationships.addAll(generateRelationshipFromParentChildAssociationRef(customParentReferences));
relationships.addAll(generateRelationshipFromParentChildAssociationRef(customParentReferences, nameFilter));
return relationships;
}
@@ -419,6 +437,18 @@ public class RelationshipServiceImpl extends RecordsManagementAdminBase implemen
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<Relationship> generateRelationshipFromAssociationRef(List<AssociationRef> associationRefs)
private Set<Relationship> generateRelationshipFromAssociationRef(List<AssociationRef> associationRefs, String nameFilter)
{
Set<Relationship> relationships = new HashSet<Relationship>();
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<Relationship> generateRelationshipFromParentChildAssociationRef(List<ChildAssociationRef> childAssociationRefs)
private Set<Relationship> generateRelationshipFromParentChildAssociationRef(List<ChildAssociationRef> childAssociationRefs, String nameFilter)
{
Set<Relationship> relationships = new HashSet<Relationship>();
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();

View File

@@ -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");

View File

@@ -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<QName> getAspects(NodeRef nodeRef) throws InvalidNodeRefException
{
@@ -190,10 +192,17 @@ public class RecordableVersionNodeServiceImpl extends Node2ServiceImpl
if (dbNodeService.hasAspect(converted, ASPECT_RECORDED_VERSION))
{
NodeRef record = (NodeRef)dbNodeService.getProperty(converted, PROP_RECORD_NODE_REF);
if (dbNodeService.exists(record))
{
Set<QName> aspects = dbNodeService.getAspects(record);
return processAspects(aspects);
}
else
{
return (Set<QName>)Collections.EMPTY_SET;
}
}
else
{
return super.getAspects(nodeRef);
}

View File

@@ -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.
* <p>
@@ -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.
* <p>
* Note this method does not destroy the associated record, instead it marks the
* version as destroyed.
*
* @param version version
*/
void destroyRecordedVersion(Version version);
}

View File

@@ -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;
@@ -502,6 +505,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)
{
result = false;
NodeRef result = null;
NodeRef versionNodeRef = getVersionNodeRef(version);
if (dbNodeService.hasAspect(versionNodeRef, RecordableVersionModel.ASPECT_RECORDED_VERSION))
{
// 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.

View File

@@ -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");

View File

@@ -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<Relationship> relationships = relationshipService.getRelationshipsFrom(record);

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<QName, Serializable> props = new HashMap<QName, Serializable>(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);
}
});
}
}

View File

@@ -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<String, Serializable> 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<String, Serializable>(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");
}
});
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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<QName, Serializable> props = new HashMap<QName, Serializable>(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<QName, Serializable> props = new HashMap<QName, Serializable>(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<Relationship> from = relationshipService.getRelationshipsFrom(versionRecord);
assertTrue(from.isEmpty());
Set<Relationship> 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<Relationship> 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<Relationship> 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<Relationship> 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<Relationship> 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<Relationship> 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<Relationship> 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<String, Serializable> params = new HashMap<String, Serializable>(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<Version> 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<Relationship> 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<Relationship> to11 = relationshipService.getRelationshipsTo(recordVersion11, "versions");
assertEquals(1, to11.size());
assertEquals(recordVersion12, to11.iterator().next().getSource());
Set<Relationship> 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<Relationship> to10 = relationshipService.getRelationshipsTo(recordVersion10, "versions");
assertEquals(1, to10.size());
assertEquals(recordVersion11, to10.iterator().next().getSource());
assertTrue(relationshipService.getRelationshipsFrom(recordVersion10, "versions").isEmpty());
}
});
}
}

View File

@@ -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
*/
@@ -56,6 +62,15 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
+ "user and smart because we support more open standards than any other ECM platform, while delivering all "
+ "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<QName, Serializable> beforeProperties = nodeService.getProperties(document);
Set<QName> beforeAspects = nodeService.getAspects(dmDocument);
Set<QName> 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());
@@ -259,4 +283,120 @@ public abstract class RecordableVersionsBaseTest extends BaseRMTestCase implemen
}
}
/**
* 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<NodeRef>()
{
@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<QName, Serializable> props = new HashMap<QName, Serializable>(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<Void>()
{
@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<Void>()
{
@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<Void>()
{
@Override
public Void run() throws Exception
{
// verify that the version history looks as expected
VersionHistory versionHistory = versionService.getVersionHistory(myDocument);
assertNotNull(versionHistory);
Collection<Version> 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<Relationship> 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<Relationship> to11 = relationshipService.getRelationshipsTo(recordVersion11, "versions");
assertEquals(1, to11.size());
assertEquals(recordVersion12, to11.iterator().next().getSource());
Set<Relationship> 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<Relationship> 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;
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@@ -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);
}
}