mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
RM-2562: Deleting records from versions produces inconsistent behaviour
* Versions are not deleted from collab version history, rather marked as destroyed (prevents inconsistencies since we don't support deleting versions well) * Share UI updated to acomadate above * Version relationship reorganised based on changes to version record history * Unit tests and integration tests for above * some unit tests relating to RM-2194 * Hover message on version record icon in version history +review RM git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.3@119284 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -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;
|
||||
@@ -71,7 +70,7 @@ public class RecordAspect extends AbstractDisposableItem
|
||||
|
||||
/** record service */
|
||||
protected RecordService recordService;
|
||||
|
||||
|
||||
/**
|
||||
* @param extendedSecurityService extended security service
|
||||
*/
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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 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 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;
|
||||
import org.alfresco.service.cmr.version.VersionHistory;
|
||||
import org.alfresco.service.cmr.version.VersionService;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* rmv:versionRecord behaviour bean
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
* @since 2.3.1
|
||||
*/
|
||||
@BehaviourBean
|
||||
(
|
||||
defaultType = "rmv:versionRecord"
|
||||
)
|
||||
public class VersionRecordAspect extends BaseBehaviourBean
|
||||
implements NodeServicePolicies.BeforeDeleteNodePolicy
|
||||
{
|
||||
/** version service */
|
||||
private VersionService versionService;
|
||||
|
||||
/** recordable version service */
|
||||
private RecordableVersionService recordableVersionService;
|
||||
|
||||
/** relationship service */
|
||||
private RelationshipService relationshipService;
|
||||
|
||||
/**
|
||||
* @param versionService version service
|
||||
*/
|
||||
public void setVersionService(VersionService versionService)
|
||||
{
|
||||
this.versionService = versionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 NodeRef versionedNodeRef = (NodeRef) nodeService.getProperty(nodeRef, PROP_VERSIONED_NODEREF);
|
||||
if (versionedNodeRef != null)
|
||||
{
|
||||
String versionLabel = (String) nodeService.getProperty(nodeRef, PROP_VERSION_LABEL);
|
||||
if (StringUtils.isNotBlank(versionLabel))
|
||||
{
|
||||
final VersionHistory versionHistory = versionService.getVersionHistory(versionedNodeRef);
|
||||
if (versionHistory != null)
|
||||
{
|
||||
final Version version = versionHistory.getVersion(versionLabel);
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -18,10 +18,6 @@
|
||||
*/
|
||||
package org.alfresco.module.org_alfresco_module_rm.record;
|
||||
|
||||
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;
|
||||
import java.util.Arrays;
|
||||
@@ -61,7 +57,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;
|
||||
@@ -122,8 +118,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);
|
||||
@@ -229,6 +224,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;
|
||||
@@ -382,6 +380,14 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
{
|
||||
this.recordsManagementContainerType = recordsManagementContainerType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param recordableVersionService recordable version service
|
||||
*/
|
||||
public void setRecordableVersionService(RecordableVersionService recordableVersionService)
|
||||
{
|
||||
this.recordableVersionService = recordableVersionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init method
|
||||
@@ -1023,7 +1029,19 @@ 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);
|
||||
|
||||
@@ -1081,7 +1099,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;
|
||||
@@ -1808,38 +1826,5 @@ public class RecordServiceImpl extends BaseBehaviourBean
|
||||
// can only unlink a record from a record folder
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
*
|
||||
@@ -85,14 +88,42 @@ public interface RelationshipService
|
||||
* @return All relationships that come out from the given node reference
|
||||
*/
|
||||
Set<Relationship> 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.
|
||||
* <p>
|
||||
* 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<Relationship> 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<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>
|
||||
|
@@ -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,20 +404,29 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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<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();
|
||||
|
@@ -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");
|
||||
|
@@ -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,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<QName> aspects = dbNodeService.getAspects(record);
|
||||
return processAspects(aspects);
|
||||
if (dbNodeService.exists(record))
|
||||
{
|
||||
Set<QName> aspects = dbNodeService.getAspects(record);
|
||||
return processAspects(aspects);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (Set<QName>)Collections.EMPTY_SET;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -47,6 +47,15 @@ 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);
|
||||
|
||||
/**
|
||||
* Creates a record from the latest version, marking it as recorded.
|
||||
* <p>
|
||||
@@ -54,8 +63,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);
|
||||
|
||||
}
|
||||
|
@@ -76,7 +76,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 +492,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 +504,66 @@ public class RecordableVersionServiceImpl extends Version2ServiceImpl
|
||||
return versionRecord;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected VersionHistory buildVersionHistory(NodeRef versionHistoryRef, NodeRef nodeRef)
|
||||
{
|
||||
VersionHistory versionHistory = super.buildVersionHistory(versionHistoryRef, nodeRef);
|
||||
|
||||
// create an empty version history if appropriate
|
||||
if (versionHistoryRef != null &&
|
||||
nodeRef != null &&
|
||||
versionHistory == null &&
|
||||
getAllVersions(versionHistoryRef).isEmpty() == true)
|
||||
{
|
||||
versionHistory = new EmptyVersionHistory();
|
||||
}
|
||||
|
||||
return versionHistory;
|
||||
}
|
||||
|
||||
public class EmptyVersionHistory implements VersionHistory
|
||||
{
|
||||
private static final long serialVersionUID = 3449832161314670033L;
|
||||
|
||||
@Override
|
||||
public Version getRootVersion()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getHeadVersion()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<Version> getAllVersions()
|
||||
{
|
||||
return (Collection<Version>)Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getPredecessor(Version version)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Collection<Version> getSuccessors(Version version)
|
||||
{
|
||||
return (Collection<Version>)Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version getVersion(String versionLabel)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Freezes audit aspect properties.
|
||||
*
|
||||
@@ -533,12 +595,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 +647,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 +826,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.
|
||||
|
Reference in New Issue
Block a user