Permalink
Browse files

Add support of move / lift restriction on filing folder types

  • Loading branch information...
AFaust committed Aug 5, 2018
1 parent 2b4e5cd commit ed9549bb94198f72fcf11161f50f593c03725d81
@@ -33,6 +33,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -278,14 +279,6 @@ public ChildAssociationRef createNode(NodeRef parentRef, QName assocTypeQName, Q
if ((Reference.fromNodeRef(parentRef) != null) && !isVirtualContextFolder(parentRef,
environment))
{
// CM-533 Suppress options to create folders in a virtual folder
// (repo)
if (environment.isSubClass(nodeTypeQName,
ContentModel.TYPE_FOLDER))
{
throw new VirtualizationException("The creation of folders within virtual folders is disabled.");
}
try
{
Reference parentReference = Reference.fromNodeRef(parentRef);
@@ -1089,13 +1082,86 @@ private void createDownloadAssociation(NodeRef sourceNodeRef, NodeRef targetRef)
public ChildAssociationRef moveNode(NodeRef nodeToMoveRef, NodeRef newParentRef, QName assocTypeQName,
QName assocQName)
{
if ((Reference.fromNodeRef(nodeToMoveRef) != null)|| (Reference.fromNodeRef(newParentRef) != null))
NodeRef actualNodeToMove = smartStore.materializeIfPossible(nodeToMoveRef);
if (Reference.fromNodeRef(actualNodeToMove) != null)
{
throw new UnsupportedOperationException("Unsuported operation for virtual source or destination");
throw new UnsupportedOperationException("Unsuported operation for virtual source");
}
NodeServiceTrait theTrait = getTrait();
if (Reference.fromNodeRef(newParentRef) != null && !isVirtualContextFolder(newParentRef,
environment))
{
QName nodeTypeQName = theTrait.getType(actualNodeToMove);
try
{
Reference parentReference = Reference.fromNodeRef(newParentRef);
FilingData filingData = smartStore.createFilingData(parentReference,
assocTypeQName,
assocQName,
nodeTypeQName,
Collections.emptyMap());
NodeRef filingNodeRef = filingData.getFilingNodeRef();
QName filingNodeTypeQName = filingData.getNodeTypeQName();
QName filingAssocTypeQName = filingData.getAssocTypeQName();
QName filingAssocQName = filingData.getAssocQName();
if (filingNodeRef != null)
{
ChildAssociationRef oldChildAssocRef = theTrait.getPrimaryParent(actualNodeToMove);
// perform physical move only if necessary
if (!filingNodeRef.equals(oldChildAssocRef.getParentRef())
|| !filingAssocTypeQName.equals(oldChildAssocRef.getTypeQName())
|| !filingAssocQName.equals(oldChildAssocRef.getQName()))
{
theTrait.moveNode(actualNodeToMove, filingNodeRef, filingAssocTypeQName,
filingAssocQName);
}
if (!nodeTypeQName.equals(filingNodeTypeQName))
{
theTrait.setType(actualNodeToMove, filingNodeTypeQName);
}
Map<QName, Serializable> filingDataProperties = filingData.getProperties();
theTrait.addProperties(actualNodeToMove, filingDataProperties);
Set<QName> aspects = filingData.getAspects();
for (QName aspect : aspects)
{
theTrait.addAspect(actualNodeToMove, aspect, filingDataProperties);
}
Reference nodeProtocolChildRef = NodeProtocol.newReference(actualNodeToMove,
parentReference);
QName vChildAssocQName = QName
.createQNameWithValidLocalName(VirtualContentModel.VIRTUAL_CONTENT_MODEL_1_0_URI,
filingAssocQName.getLocalName());
ChildAssociationRef childAssocRef = new ChildAssociationRef(filingAssocTypeQName,
newParentRef,
vChildAssocQName,
nodeProtocolChildRef.toNodeRef());
return childAssocRef;
}
else
{
throw new InvalidNodeRefException("Can not move node to parent ", newParentRef);
}
}
catch (VirtualizationException e)
{
throw new InvalidNodeRefException("Could not move node into virtual context.",
newParentRef,
e);
}
}
else
{
return getTrait().moveNode(nodeToMoveRef,
return theTrait.moveNode(nodeToMoveRef,
newParentRef,
assocTypeQName,
assocQName);
@@ -106,35 +106,14 @@ private FilingData createFilingData(Reference parentRef, QName assocTypeQName, Q
{
fType = QName.createQName(type,
nsPrefixResolver);
// CM-528 acceptance criteria 3 :
// Given that the current user can upload new content into a
// specific virtual folder (filing rule)
// when a filing rule specifies a type or sub type of cm:folder
// (which is a non supported configuration)
// uploading content will create a document, not a folder
if (env.isSubClass(fType,
ContentModel.TYPE_FOLDER))
{
if (logger.isDebugEnabled())
{
logger.debug("CM-528 acceptance criteria 3 : we deny the creation of folders subtype " + fType
+ " and force cm:content instead.");
}
fType = ContentModel.TYPE_CONTENT;
}
// Explicit type matching follows.
// It might cause non-transactional behavior.
// To avoid it we rely on folder creation exclusion in
// VirtualNodeServiceExtension#createNode
// See CM-533 Suppress options to create folders in a virtual folder
if (env.isSubClass(nodeTypeQName,
fType))
if (env.isSubClass(nodeTypeQName, fType))
{
fType = nodeTypeQName;
}
else if (!env.isSubClass(fType, nodeTypeQName))
{
throw new VirtualizationException("The filing rule for the virtual folder specifies an incompatible node type.");
}
}
@@ -161,9 +161,6 @@
</property>
<property name="denyQueryNodes">
<set>
<value>ChangePermissions</value>
<value>DeleteNode</value>
<value>Delete</value>
</set>
</property>
</bean>
@@ -58,11 +58,15 @@
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.ref.VirtualProtocol;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.CopyService;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern;
@@ -192,7 +196,7 @@ public void testCreate_NodeProtocolParent() throws Exception
}
@Test
public void testCreateNode_CM_528_folder_filing_type() throws Exception
public void testCreateNode_incompatible_filing_type() throws Exception
{
NodeRef testTemplate5 = createVirtualizedFolder(testRootFolder.getNodeRef(),
"aVFTestTemplate5",
@@ -201,13 +205,17 @@ public void testCreateNode_CM_528_folder_filing_type() throws Exception
ContentModel.ASSOC_CONTAINS,
"FolderFilingType");
ChildAssociationRef forcedCmContentAssocRef = createContent(folderFilingTypeNode,
"forcedCmContent");
NodeRef forcedCmContent = forcedCmContentAssocRef.getChildRef();
QName actualType = nodeService.getType(forcedCmContent);
assertEquals(ContentModel.TYPE_CONTENT,
actualType);
try
{
createContent(folderFilingTypeNode, "incompatibleFilingType");
fail("Should not be able to create cm:content with filing rule set to cm:folder");
}
catch (InvalidNodeRefException e)
{
assertEquals("Could not create node in virtual context.", e.getMessage());
logger.info("Successfully denied creation of incompatible node type",
e);
}
}
@Test
@@ -1291,6 +1299,75 @@ public void testHasAspect() throws Exception
resetMocks();
}
}
@Test
public void testMoveNode_existingNodeIntoVirtualFolderWithPropertyUpdate()
{
FileInfo normalFolder = fileAndFolderService.create(companyHomeNodeRef,
"normal-folder",
ContentModel.TYPE_FOLDER);
FileInfo normalFile = fileAndFolderService.create(normalFolder.getNodeRef(),
"regular-file.txt",
ContentModel.TYPE_CONTENT);
NodeRef testTemplate1 = createVirtualizedFolder(testRootFolder.getNodeRef(),
"aVFTestTemplate1",
TEST_TEMPLATE_1_JSON_SYS_PATH);
NodeRef virtualFolderNode = nodeService.getChildByName(testTemplate1,
ContentModel.ASSOC_CONTAINS,
"Node1");
ChildAssociationRef oldFilePrimaryParent = nodeService.getPrimaryParent(normalFile.getNodeRef());
nodeService.moveNode(normalFile.getNodeRef(), virtualFolderNode,
oldFilePrimaryParent.getTypeQName(),
oldFilePrimaryParent.getQName());
assertNotNull(nodeService.getChildByName(virtualFolderNode, ContentModel.ASSOC_CONTAINS,
"regular-file.txt"));
String description = (String) nodeService.getProperty(normalFile.getNodeRef(),
ContentModel.PROP_DESCRIPTION);
assertEquals("TheNode1", description);
}
@Test
public void testMoveNode_existingNodeBetweenVirtualFoldersWithPropertyAndAspectUpdates()
{
NodeRef testTemplate1 = createVirtualizedFolder(testRootFolder.getNodeRef(),
"aVFTestTemplate1",
TEST_TEMPLATE_1_JSON_SYS_PATH);
NodeRef virtualFolderNode1 = nodeService.getChildByName(testTemplate1,
ContentModel.ASSOC_CONTAINS,
"Node1");
assertNotNull(virtualFolderNode1);
NodeRef virtualFolderNode2 = nodeService.getChildByName(testTemplate1,
ContentModel.ASSOC_CONTAINS,
"Node2");
assertNotNull(virtualFolderNode2);
NodeRef virtualFolderNode2_1 = nodeService.getChildByName(virtualFolderNode2,
ContentModel.ASSOC_CONTAINS,
"Node2_1");
assertNotNull(virtualFolderNode2_1);
ChildAssociationRef nodeToMoveChildRef = createContent(virtualFolderNode1, "nodeToMove");
NodeRef nodeToMoveRef = nodeToMoveChildRef.getChildRef();
String description1 = (String) nodeService.getProperty(nodeToMoveRef,
ContentModel.PROP_DESCRIPTION);
assertEquals("TheNode1", description1);
assertFalse(nodeService.hasAspect(nodeToMoveRef, ContentModel.ASPECT_AUTHOR));
assertFalse(nodeService.hasAspect(nodeToMoveRef, ContentModel.ASPECT_DUBLINCORE));
ChildAssociationRef movedNodeChildRef = nodeService.moveNode(nodeToMoveRef, virtualFolderNode2_1,
nodeToMoveChildRef.getTypeQName(),
nodeToMoveChildRef.getQName());
NodeRef movedNodeRef = movedNodeChildRef.getChildRef();
String description2_1 = (String) nodeService.getProperty(movedNodeRef, ContentModel.PROP_DESCRIPTION);
assertEquals("Node2_1Desc", description2_1);
assertTrue(nodeService.hasAspect(movedNodeRef, ContentModel.ASPECT_AUTHOR));
assertTrue(nodeService.hasAspect(movedNodeRef, ContentModel.ASPECT_DUBLINCORE));
assertNotNull(nodeService.getChildByName(virtualFolderNode2_1, ContentModel.ASSOC_CONTAINS,
"nodeToMove"));
}
private NodeRef createDownloadNode()
{

0 comments on commit ed9549b

Please sign in to comment.