mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-08 14:51:49 +00:00
Merge branch 'feature/RM-4296_IllegalChildrenInFileplanRoot' into 'master'
Feature/rm 4296 illegal children in fileplan root RM-4296 - Create special containers as File Plan works You could create children of any node type in fileplan root except for content and record folder because we were blacklisting the denied types. Whitelisted the accepted types dividing them in 2 categories: types that are accepted only once and types that are accepted multiple types See merge request !601
This commit is contained in:
@@ -27,16 +27,22 @@
|
||||
|
||||
package org.alfresco.module.org_alfresco_module_rm.model;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
import org.alfresco.repo.policy.annotation.BehaviourRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Convenient base class for behaviour beans.
|
||||
*
|
||||
@@ -87,4 +93,28 @@ public abstract class BaseBehaviourBean extends ServiceBaseImpl
|
||||
return behaviours.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that checks if the newly created child association complies with the RM rules
|
||||
* @param parent the parent node
|
||||
* @param childType the child node
|
||||
* @param acceptedUniqueChildType a list of node types that are accepted as children of the provided parent only once
|
||||
* @param acceptedMultipleChildType a list of node types that are accepted as children of the provided parent multiple times
|
||||
* @throws InvalidParameterException if the child association doesn't comply with the RM rules
|
||||
*/
|
||||
protected void validateNewChildAssociation(NodeRef parent, NodeRef child, List<QName> acceptedUniqueChildType, List<QName> acceptedMultipleChildType) throws InvalidParameterException
|
||||
{
|
||||
QName childType = getInternalNodeService().getType(child);
|
||||
if(acceptedUniqueChildType.contains(childType))
|
||||
{
|
||||
// check the user is not trying to create multiple children of a type that is only accepted once
|
||||
if(nodeService.getChildAssocs(parent, Sets.newHashSet(childType)).size() > 1)
|
||||
{
|
||||
throw new InvalidParameterException("Operation failed. Multiple children of this type are not allowed.");
|
||||
}
|
||||
}
|
||||
else if(!acceptedMultipleChildType.contains(childType))
|
||||
{
|
||||
throw new InvalidParameterException("Operation failed. Children of type " + childType + " are not allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -27,8 +27,10 @@
|
||||
|
||||
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
|
||||
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
|
||||
@@ -45,6 +47,9 @@ 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;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* rma:filePlan behaviour bean
|
||||
@@ -61,6 +66,9 @@ public class FilePlanType extends BaseBehaviourBean
|
||||
NodeServicePolicies.OnCreateNodePolicy,
|
||||
NodeServicePolicies.OnDeleteNodePolicy
|
||||
{
|
||||
private static List<QName> ACCEPTED_UNIQUE_CHILD_TYPES = Arrays.asList(TYPE_HOLD_CONTAINER, TYPE_TRANSFER_CONTAINER, TYPE_UNFILED_RECORD_CONTAINER);
|
||||
private static List<QName> ACCEPTED_NON_UNIQUE_CHILD_TYPES = Arrays.asList(TYPE_RECORD_CATEGORY);
|
||||
|
||||
/** file plan service */
|
||||
private FilePlanService filePlanService;
|
||||
|
||||
@@ -147,20 +155,8 @@ public class FilePlanType extends BaseBehaviourBean
|
||||
@Override
|
||||
public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean bNew)
|
||||
{
|
||||
// ensure we are not trying to put content in the file plan root node
|
||||
NodeRef nodeRef = childAssocRef.getChildRef();
|
||||
if (instanceOf(nodeRef, ContentModel.TYPE_CONTENT))
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Operation failed, because you can't place content in the root of the file plan.");
|
||||
}
|
||||
|
||||
// ensure we are not trying to put a record folder in the root of the file plan
|
||||
NodeRef parent = childAssocRef.getParentRef();
|
||||
if (getFilePlanService().isFilePlan(parent) && getRecordFolderService().isRecordFolder(nodeRef))
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Operation failed, because you can not place a record folder in the root of the file plan.");
|
||||
}
|
||||
|
||||
// check the created child is of an accepted type
|
||||
validateNewChildAssociation(childAssocRef.getParentRef(), childAssocRef.getChildRef(), ACCEPTED_UNIQUE_CHILD_TYPES, ACCEPTED_NON_UNIQUE_CHILD_TYPES);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Records Management Module
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* -
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
* -
|
||||
* 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/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Unit test that test the conditions enforced by FilePlanType behavior bean
|
||||
*
|
||||
* @author Ana Bozianu
|
||||
* @since 2.6
|
||||
*/
|
||||
public class FilePlanTypeUnitTest extends BaseUnitTest
|
||||
{
|
||||
|
||||
/** test object */
|
||||
private @InjectMocks FilePlanType filePlanType;
|
||||
|
||||
/** existing fileplan node */
|
||||
private NodeRef filePlanContainer;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
filePlanContainer = generateNodeRef(TYPE_FILE_PLAN, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Having the Fileplan container
|
||||
* When adding a child of type TYPE_FILE_PLAN
|
||||
* Then an error should be thrown
|
||||
*/
|
||||
@Test (expected = InvalidParameterException.class)
|
||||
public void testAddFileplanToFileplan()
|
||||
{
|
||||
ChildAssociationRef childAssoc = createFileplanContainerChild(TYPE_FILE_PLAN);
|
||||
filePlanType.onCreateChildAssociation(childAssoc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Having the Fileplan container
|
||||
* When adding multiple child of type TYPE_RECORD_CATEGORY
|
||||
* Then child associations should be created
|
||||
*/
|
||||
@Test
|
||||
public void testAddCategoriesToFileplan()
|
||||
{
|
||||
// add the first child
|
||||
ChildAssociationRef childAssoc1 = createFileplanContainerChild(TYPE_RECORD_CATEGORY);
|
||||
filePlanType.onCreateChildAssociation(childAssoc1, true);
|
||||
|
||||
// add the second child
|
||||
ChildAssociationRef childAssoc2 = createFileplanContainerChild(TYPE_RECORD_CATEGORY);
|
||||
filePlanType.onCreateChildAssociation(childAssoc2, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Having the Fileplan container
|
||||
* When creating the first child of type TYPE_HOLD_CONTAINER
|
||||
* Then the fileplan behavior bean shouldn't complain
|
||||
*/
|
||||
@Test
|
||||
public void testCreateHoldContainers()
|
||||
{
|
||||
ChildAssociationRef childAssoc = createFileplanContainerChild(TYPE_HOLD_CONTAINER);
|
||||
|
||||
when(mockedNodeService.getChildAssocs(filePlanContainer, Sets.newHashSet(TYPE_HOLD_CONTAINER))).thenReturn(Arrays.asList(childAssoc));
|
||||
filePlanType.onCreateChildAssociation(childAssoc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Having the Fileplan container with a child of type TYPE_HOLD_CONTAINER
|
||||
* When adding another child of type TYPE_HOLD_CONTAINER
|
||||
* Then an error should be thrown
|
||||
*/
|
||||
@Test (expected = InvalidParameterException.class)
|
||||
public void testCreateMultipleHoldContainers()
|
||||
{
|
||||
ChildAssociationRef existingHoldAssoc = createFileplanContainerChild(TYPE_HOLD_CONTAINER);
|
||||
ChildAssociationRef childAssoc = createFileplanContainerChild(TYPE_HOLD_CONTAINER);
|
||||
|
||||
when(mockedNodeService.getChildAssocs(filePlanContainer, Sets.newHashSet(TYPE_HOLD_CONTAINER))).thenReturn(Arrays.asList(existingHoldAssoc, childAssoc));
|
||||
filePlanType.onCreateChildAssociation(childAssoc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Having the Fileplan container
|
||||
* When creating the first child of type TYPE_TRANSFER_CONTAINER
|
||||
* Then the fileplan behavior bean shouldn't complain
|
||||
*/
|
||||
@Test
|
||||
public void testCreateTransferContainers()
|
||||
{
|
||||
ChildAssociationRef childAssoc = createFileplanContainerChild(TYPE_TRANSFER_CONTAINER);
|
||||
|
||||
when(mockedNodeService.getChildAssocs(filePlanContainer, Sets.newHashSet(TYPE_TRANSFER_CONTAINER))).thenReturn(Arrays.asList(childAssoc));
|
||||
filePlanType.onCreateChildAssociation(childAssoc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Having the Fileplan container with a child of type TYPE_TRANSFER_CONTAINER
|
||||
* When adding another child of type TYPE_TRANSFER_CONTAINER
|
||||
* Then an error should be thrown
|
||||
*/
|
||||
@Test (expected = InvalidParameterException.class)
|
||||
public void testCreateMultipleTransferContainers()
|
||||
{
|
||||
ChildAssociationRef existingHoldAssoc = createFileplanContainerChild(TYPE_TRANSFER_CONTAINER);
|
||||
ChildAssociationRef childAssoc = createFileplanContainerChild(TYPE_TRANSFER_CONTAINER);
|
||||
|
||||
when(mockedNodeService.getChildAssocs(filePlanContainer, Sets.newHashSet(TYPE_TRANSFER_CONTAINER))).thenReturn(Arrays.asList(existingHoldAssoc, childAssoc));
|
||||
filePlanType.onCreateChildAssociation(childAssoc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Having the Fileplan container
|
||||
* When creating the first child of type TYPE_UNFILED_RECORD_CONTAINER
|
||||
* Then the fileplan behavior bean shouldn't complain
|
||||
*/
|
||||
@Test
|
||||
public void testCreateUnfiledRecordsContainers()
|
||||
{
|
||||
ChildAssociationRef childAssoc = createFileplanContainerChild(TYPE_UNFILED_RECORD_CONTAINER);
|
||||
|
||||
when(mockedNodeService.getChildAssocs(filePlanContainer, Sets.newHashSet(TYPE_UNFILED_RECORD_CONTAINER))).thenReturn(Arrays.asList(childAssoc));
|
||||
filePlanType.onCreateChildAssociation(childAssoc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Having the Fileplan container with a child of type TYPE_UNFILED_RECORD_CONTAINER
|
||||
* When adding another child of type TYPE_UNFILED_RECORD_CONTAINER
|
||||
* Then an error should be thrown
|
||||
*/
|
||||
@Test (expected = InvalidParameterException.class)
|
||||
public void testCreateMultipleUnfiledRecordsContainers()
|
||||
{
|
||||
ChildAssociationRef existingHoldAssoc = createFileplanContainerChild(TYPE_UNFILED_RECORD_CONTAINER);
|
||||
ChildAssociationRef childAssoc = createFileplanContainerChild(TYPE_UNFILED_RECORD_CONTAINER);
|
||||
|
||||
when(mockedNodeService.getChildAssocs(filePlanContainer, Sets.newHashSet(TYPE_UNFILED_RECORD_CONTAINER))).thenReturn(Arrays.asList(existingHoldAssoc, childAssoc));
|
||||
filePlanType.onCreateChildAssociation(childAssoc, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that creates a child of the fileplan container with the provided type
|
||||
* @param childType the node type of the child to be created
|
||||
* @return the child association between the fileplan and the created node
|
||||
*/
|
||||
private ChildAssociationRef createFileplanContainerChild(QName childType)
|
||||
{
|
||||
NodeRef child = generateNodeRef(childType);
|
||||
return new ChildAssociationRef( ContentModel.ASSOC_CONTAINS, filePlanContainer, childType, child);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user