diff --git a/.gitignore b/.gitignore
index dfdc3e2322..f5146b465f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,6 @@ test-output
/rm-enterprise/rm-automation-enterprise/root
rm-automation/src/test/resources/webdriver.properties
+
+/rm-community/rm-community-rest-api-explorer/overlays
+/rm-enterprise/rm-enterprise-rest-api-explorer/overlays
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
index e8eeae8602..b7d1e33fd6 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
@@ -94,4 +94,35 @@
+
+
+
+
+ TRANSFER_CONTAINER
+
+
+
+
+
+
+
+
+
+
+
+
+ HOLD_CONTAINER
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-group-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-group-context.xml
index 91a50ef89d..3b67d92639 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-group-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-group-context.xml
@@ -25,6 +25,8 @@
+
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
index 7eb9c17eda..8fe840ba94 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-model-context.xml
@@ -76,6 +76,9 @@
+
+
+
@@ -84,6 +87,14 @@
+
+
+
+
+
+
+
@@ -105,6 +116,7 @@
+
diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index 0298088a35..f7e95ba278 100644
--- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -173,6 +173,8 @@
+
+
@@ -579,9 +581,9 @@
parent="baseService">
-
-
-
+
+
+
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/BaseBehaviourBean.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/BaseBehaviourBean.java
index bd09ccb6b1..4fc2b96b93 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/BaseBehaviourBean.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/BaseBehaviourBean.java
@@ -27,15 +27,20 @@
package org.alfresco.module.org_alfresco_module_rm.model;
+import com.google.common.collect.Sets;
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.node.integrity.IntegrityException;
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 org.springframework.extensions.surf.util.I18NUtil;
/**
* Convenient base class for behaviour beans.
@@ -50,6 +55,12 @@ public abstract class BaseBehaviourBean extends ServiceBaseImpl
/** Logger */
protected static final Log LOGGER = LogFactory.getLog(BaseBehaviourBean.class);
+ /**
+ * I18N
+ */
+ protected static final String UNIQUE_CHILD_TYPE_ERROR = "rm.action.unique.child.type-error-message";
+ protected static final String MULTIPLE_CHILDREN_TYPE_ERROR = "rm.action.multiple.children.type-error-message";
+
/** behaviour filter */
protected BehaviourFilter behaviourFilter;
@@ -87,4 +98,52 @@ 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 IntegrityException if the child association doesn't comply with the RM rules
+ */
+ protected void validateNewChildAssociation(NodeRef parent, NodeRef child, List acceptedUniqueChildType, List acceptedMultipleChildType) throws IntegrityException
+ {
+ 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 IntegrityException(I18NUtil.getMessage(UNIQUE_CHILD_TYPE_ERROR), null);
+ }
+ }
+ else if (!acceptedMultipleChildType.contains(childType))
+ {
+ throw new IntegrityException(I18NUtil.getMessage(MULTIPLE_CHILDREN_TYPE_ERROR, childType), null);
+ }
+ }
+
+ /**
+ * Helper method that checks if the newly created child association is between the sub-types of accepted types.
+ *
+ * @param child the child node
+ * @param acceptedMultipleChildType a list of node types that are accepted as children of the provided parent multiple times
+ * @throws IntegrityException if the child association isn't between the sub-types of accepted types
+ */
+ protected void validateNewChildAssociationSubTypesIncluded(NodeRef child, List acceptedMultipleChildType)
+ throws IntegrityException
+ {
+ QName childType = getInternalNodeService().getType(child);
+ for (QName type : acceptedMultipleChildType)
+ {
+ if (instanceOf(childType, type))
+ {
+ return;
+ }
+ }
+ //no match was found in sub-types of permitted types list
+ throw new IntegrityException(I18NUtil.getMessage(MULTIPLE_CHILDREN_TYPE_ERROR, childType), null);
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/FilePlanType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/FilePlanType.java
index 8344e8f696..485c7b5543 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/FilePlanType.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/FilePlanType.java
@@ -27,7 +27,8 @@
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
-import org.alfresco.error.AlfrescoRuntimeException;
+import java.util.Arrays;
+import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
@@ -36,6 +37,7 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
@@ -45,6 +47,7 @@ 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;
/**
* rma:filePlan behaviour bean
@@ -59,8 +62,13 @@ import org.alfresco.service.cmr.repository.NodeRef;
public class FilePlanType extends BaseBehaviourBean
implements NodeServicePolicies.OnCreateChildAssociationPolicy,
NodeServicePolicies.OnCreateNodePolicy,
- NodeServicePolicies.OnDeleteNodePolicy
+ NodeServicePolicies.OnDeleteNodePolicy,
+ NodeServicePolicies.BeforeDeleteNodePolicy
{
+ private final static List ACCEPTED_UNIQUE_CHILD_TYPES = Arrays.asList(TYPE_HOLD_CONTAINER, TYPE_TRANSFER_CONTAINER, TYPE_UNFILED_RECORD_CONTAINER);
+ private final static List ACCEPTED_NON_UNIQUE_CHILD_TYPES = Arrays.asList(TYPE_RECORD_CATEGORY);
+ private static final String BEHAVIOUR_NAME = "onDeleteFilePlan";
+
/** file plan service */
private FilePlanService filePlanService;
@@ -73,6 +81,21 @@ public class FilePlanType extends BaseBehaviourBean
/** file plan role service */
private FilePlanRoleService filePlanRoleService;
+ /**
+ * Unfiled Record Container Type behaviour bean
+ */
+ private UnfiledRecordContainerType unfilerRecordContainerType;
+
+ /**
+ * Transfer Container Type behaviour bean
+ */
+ private TransferContainerType transferContainerType;
+
+ /**
+ * Hold Container Type behaviour bean
+ */
+ private HoldContainerType holdContainerType;
+
/**
* @return File plan service
*/
@@ -137,6 +160,46 @@ public class FilePlanType extends BaseBehaviourBean
this.filePlanRoleService = filePlanRoleService;
}
+ /**
+ * @param unfilerRecordContainerType - unfiled record container type behaviour bean
+ */
+ public void setUnfilerRecordContainerType(UnfiledRecordContainerType unfilerRecordContainerType)
+ {
+ this.unfilerRecordContainerType = unfilerRecordContainerType;
+ }
+
+ /**
+ * @param transferContainerType - transfer container type behaviour bean
+ */
+ public void setTransferContainerType(TransferContainerType transferContainerType)
+ {
+ this.transferContainerType = transferContainerType;
+ }
+
+ /**
+ * @param holdContainerType - hold container type behaviour bean
+ */
+ public void setHoldContainerType(HoldContainerType holdContainerType)
+ {
+ this.holdContainerType = holdContainerType;
+ }
+
+ /**
+ * Disable the behaviours for this transaction
+ */
+ public void disable()
+ {
+ getBehaviour(BEHAVIOUR_NAME).disable();
+ }
+
+ /**
+ * Enable behaviours for this transaction
+ */
+ public void enable()
+ {
+ getBehaviour(BEHAVIOUR_NAME).enable();
+ }
+
/**
* @see org.alfresco.repo.node.NodeServicePolicies.OnCreateChildAssociationPolicy#onCreateChildAssociation(org.alfresco.service.cmr.repository.ChildAssociationRef, boolean)
*/
@@ -147,20 +210,17 @@ 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))
+ // We need to automatically cast the created folder to category if it is a plain folder
+ // This occurs if the RM folder has been created via IMap, WebDav, etc. Don't check subtypes.
+ // Some modules use hidden files to store information (see RM-3283)
+ if (nodeService.getType(childAssocRef.getChildRef())
+ .equals(ContentModel.TYPE_FOLDER))
{
- 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.");
+ nodeService.setType(childAssocRef.getChildRef(), TYPE_RECORD_CATEGORY);
}
+ // check the created child is of an accepted type
+ validateNewChildAssociation(childAssocRef.getParentRef(), childAssocRef.getChildRef(), ACCEPTED_UNIQUE_CHILD_TYPES, ACCEPTED_NON_UNIQUE_CHILD_TYPES);
}
/**
@@ -182,8 +242,8 @@ public class FilePlanType extends BaseBehaviourBean
{
// ensure rules are not inherited
nodeService.addAspect(filePlan, RuleModel.ASPECT_IGNORE_INHERITED_RULES, null);
-
- // set the identifier
+
+ // set the identifier
if (nodeService.getProperty(filePlan, PROP_IDENTIFIER) == null)
{
String id = getIdentifierService().generateIdentifier(filePlan);
@@ -201,15 +261,40 @@ public class FilePlanType extends BaseBehaviourBean
/**
* @see org.alfresco.repo.node.NodeServicePolicies.OnDeleteNodePolicy#onDeleteNode(org.alfresco.service.cmr.repository.ChildAssociationRef, boolean)
*/
- @Behaviour
- (
- kind = BehaviourKind.CLASS,
- notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT
- )
@Override
+ @Behaviour(kind = BehaviourKind.CLASS,
+ notificationFrequency = NotificationFrequency.FIRST_EVENT,
+ name = BEHAVIOUR_NAME)
public void onDeleteNode(ChildAssociationRef childAssocRef, boolean archived)
+ {
+ unfilerRecordContainerType.enable();
+ transferContainerType.enable();
+ holdContainerType.enable();
+ throw new IntegrityException("Operation failed. Deletion of File Plan is not allowed.", null);
+ }
+
+ /**
+ * @see org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy#beforeDeleteNode(org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ @Behaviour(kind = BehaviourKind.CLASS,
+ notificationFrequency = NotificationFrequency.FIRST_EVENT)
+ public void beforeDeleteNode(NodeRef nodeRef)
+ {
+ unfilerRecordContainerType.disable();
+ transferContainerType.disable();
+ holdContainerType.disable();
+ }
+
+ @Behaviour(kind = BehaviourKind.CLASS,
+ policy = "alf:onDeleteNode",
+ notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT)
+ public void onDeleteNodeOnCommit(ChildAssociationRef childAssocRef, boolean archived)
{
// tear down the file plan roles
getFilePlanRoleService().tearDownFilePlanRoles(childAssocRef.getChildRef());
+ unfilerRecordContainerType.enable();
+ transferContainerType.enable();
+ holdContainerType.enable();
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/HoldContainerType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/HoldContainerType.java
index 16e233e3aa..937f5de737 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/HoldContainerType.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/HoldContainerType.java
@@ -26,15 +26,19 @@
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
+import java.util.Arrays;
+import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.namespace.QName;
import org.springframework.extensions.surf.util.I18NUtil;
/**
@@ -45,9 +49,29 @@ import org.springframework.extensions.surf.util.I18NUtil;
*/
@BehaviourBean(defaultType = "rma:holdContainer")
public class HoldContainerType extends BaseBehaviourBean
- implements NodeServicePolicies.OnCreateChildAssociationPolicy, NodeServicePolicies.OnCreateNodePolicy
+ implements NodeServicePolicies.OnCreateChildAssociationPolicy,
+ NodeServicePolicies.OnCreateNodePolicy,
+ NodeServicePolicies.OnDeleteNodePolicy
{
private final static String MSG_ERROR_ADD_CONTENT_CONTAINER = "rm.service.error-add-content-container";
+ private final static List ACCEPTED_NON_UNIQUE_CHILD_TYPES = Arrays.asList(TYPE_HOLD);
+ private static final String DELETE_BEHAVIOUR_NAME = "onDeleteHoldContainer";
+
+ /**
+ * Disable the behaviours for this transaction
+ */
+ public void disable()
+ {
+ getBehaviour(DELETE_BEHAVIOUR_NAME).disable();
+ }
+
+ /**
+ * Enable behaviours for this transaction
+ */
+ public void enable()
+ {
+ getBehaviour(DELETE_BEHAVIOUR_NAME).enable();
+ }
/**
* On every event
@@ -59,11 +83,8 @@ public class HoldContainerType extends BaseBehaviourBean
@Behaviour(kind = BehaviourKind.ASSOCIATION)
public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean bNew)
{
-
- NodeRef nodeRef = childAssocRef.getChildRef();
- if (instanceOf(nodeRef, ContentModel.TYPE_CONTENT) == true) { throw new AlfrescoRuntimeException(
- I18NUtil.getMessage(MSG_ERROR_ADD_CONTENT_CONTAINER)); }
-
+ // check the created child is of an accepted type
+ validateNewChildAssociationSubTypesIncluded(childAssocRef.getChildRef(), ACCEPTED_NON_UNIQUE_CHILD_TYPES);
}
@Override
@@ -74,4 +95,12 @@ public class HoldContainerType extends BaseBehaviourBean
I18NUtil.getMessage(MSG_ERROR_ADD_CONTENT_CONTAINER)); }
}
+
+ @Override
+ @Behaviour(kind = BehaviourKind.CLASS,
+ name = DELETE_BEHAVIOUR_NAME)
+ public void onDeleteNode(ChildAssociationRef childAssocRef, boolean isNodeArchived)
+ {
+ throw new IntegrityException("Operation failed. Deletion of Hold Container is not allowed.", null);
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordCategoryType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordCategoryType.java
index 81dc259b95..eee8199119 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordCategoryType.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RecordCategoryType.java
@@ -27,6 +27,9 @@
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
@@ -62,6 +65,9 @@ public class RecordCategoryType extends BaseBehaviourBean
NodeServicePolicies.OnCreateNodePolicy,
NodeServicePolicies.OnMoveNodePolicy
{
+ private final static List ACCEPTED_UNIQUE_CHILD_TYPES = new ArrayList();
+ private final static List ACCEPTED_NON_UNIQUE_CHILD_TYPES = Arrays.asList(TYPE_RECORD_CATEGORY, TYPE_RECORD_FOLDER);
+
/** vital record service */
protected VitalRecordService vitalRecordService;
@@ -107,17 +113,22 @@ public class RecordCategoryType extends BaseBehaviourBean
)
public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean bNew)
{
- // ensure content is not placed directly into a record category
- NodeRef nodeRef = childAssocRef.getChildRef();
- if (instanceOf(nodeRef, ContentModel.TYPE_CONTENT))
+ QName childType = nodeService.getType(childAssocRef.getChildRef());
+
+ // We need to automatically cast the created folder to record folder if it is a plain folder
+ // This occurs if the RM folder has been created via IMap, WebDav, etc. Don't check subtypes.
+ // Some modules use hidden folders to store information (see RM-3283).
+ if (childType.equals(ContentModel.TYPE_FOLDER))
{
- throw new AlfrescoRuntimeException("Operation failed, because you can't place content directly into a record category.");
+ nodeService.setType(childAssocRef.getChildRef(), TYPE_RECORD_FOLDER);
}
+ validateNewChildAssociation(childAssocRef.getParentRef(), childAssocRef.getChildRef(), ACCEPTED_UNIQUE_CHILD_TYPES, ACCEPTED_NON_UNIQUE_CHILD_TYPES);
+
if (bNew)
{
// setup the record folder
- recordFolderService.setupRecordFolder(nodeRef);
+ recordFolderService.setupRecordFolder(childAssocRef.getChildRef());
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RmSiteType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RmSiteType.java
index 63fb27c048..682589598a 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RmSiteType.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/RmSiteType.java
@@ -27,15 +27,20 @@
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
+import com.google.common.collect.Sets;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-
import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService;
import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
@@ -54,6 +59,7 @@ import org.alfresco.service.cmr.site.SiteVisibility;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
import org.alfresco.util.PropertyMap;
+import org.springframework.extensions.surf.util.I18NUtil;
/**
* Behaviour associated with the RM Site type
@@ -68,12 +74,14 @@ import org.alfresco.util.PropertyMap;
public class RmSiteType extends BaseBehaviourBean
implements NodeServicePolicies.OnCreateNodePolicy,
NodeServicePolicies.OnUpdatePropertiesPolicy,
- NodeServicePolicies.BeforeDeleteNodePolicy
+ NodeServicePolicies.BeforeDeleteNodePolicy,
+ NodeServicePolicies.OnCreateChildAssociationPolicy
{
- /** Constant values */
- public static final String COMPONENT_DOCUMENT_LIBRARY = "documentLibrary";
+ /** Constant values */
+ public static final String COMPONENT_DOCUMENT_LIBRARY = "documentLibrary";
public static final String DEFAULT_SITE_NAME = "rm";
public static final QName DEFAULT_FILE_PLAN_TYPE = TYPE_FILE_PLAN;
+ private final static List ACCEPTED_NON_UNIQUE_CHILD_TYPES = Arrays.asList(ContentModel.TYPE_FOLDER);
/** Site service */
protected SiteService siteService;
@@ -87,6 +95,8 @@ public class RmSiteType extends BaseBehaviourBean
/** Authority service */
private AuthorityService authorityService;
+ private FilePlanType filePlanType;
+
/** Map of file plan type's key'ed by corresponding site types */
protected Map mapFilePlanType = new HashMap(3);
@@ -123,6 +133,11 @@ public class RmSiteType extends BaseBehaviourBean
this.authorityService = authorityService;
}
+ public void setFilePlanType(FilePlanType filePlanType)
+ {
+ this.filePlanType = filePlanType;
+ }
+
/**
* Registers a file plan type for a specific site type.
*
@@ -292,7 +307,63 @@ public class RmSiteType extends BaseBehaviourBean
return null;
}
});
+ filePlanType.disable();
}
}
}
+
+ /**
+ * Add the limitation of creating only one rma:filePlan or one dod:filePlan depending on the type of rm site.
+ * Also added the limitation of crating two cm:folder type under rm site.
+ * Other than this nothing can be created under rm site nodeRef
+ *
+ * @author Silviu Dinuta
+ * @since 2.6
+ */
+ @Override
+ @Behaviour(kind = BehaviourKind.ASSOCIATION)
+ public void onCreateChildAssociation(final ChildAssociationRef childAssocRef, boolean isNewNode)
+ {
+ AuthenticationUtil.runAsSystem(new RunAsWork()
+ {
+ @Override
+ public Void doWork()
+ {
+ final NodeRef child = childAssocRef.getChildRef();
+ final NodeRef parent = childAssocRef.getParentRef();
+ List acceptedUniqueChildTypes = new ArrayList();
+ SiteInfo siteInfo = siteService.getSite(parent);
+ acceptedUniqueChildTypes.add(getFilePlanType(siteInfo));
+ // check the created child is of an accepted type
+ validateNewChildAssociation(parent, child, acceptedUniqueChildTypes, ACCEPTED_NON_UNIQUE_CHILD_TYPES);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Overridden this because in this case we need to have multiple cm:folder types but not more than two of them.
+ * The two mentioned folders are created when rm site is created and one of them is Saved Searches and the other surf-config folder.
+ * After that creation of cm:folder should not be allowed under rm site node
+ */
+ @Override
+ protected void validateNewChildAssociation(NodeRef parent, NodeRef child, List acceptedUniqueChildType,
+ List acceptedMultipleChildType) throws IntegrityException
+ {
+ super.validateNewChildAssociation(parent, child, acceptedUniqueChildType, acceptedMultipleChildType);
+
+ // check the user is not trying to create more than 2 folders that are created by default.
+ if (nodeService.getChildAssocs(parent, Sets.newHashSet(ContentModel.TYPE_FOLDER)).size() > 2)
+ {
+ throw new IntegrityException(I18NUtil.getMessage(MULTIPLE_CHILDREN_TYPE_ERROR, ContentModel.TYPE_FOLDER), null);
+ }
+ }
+
+ @Behaviour(kind = BehaviourKind.CLASS,
+ policy = "alf:onDeleteNode",
+ notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT)
+ public void onDeleteNodeOnCommit(ChildAssociationRef childAssocRef, boolean isNodeArchived)
+ {
+ filePlanType.enable();
+ }
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferContainerType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferContainerType.java
index 753e4b2036..06694e3308 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferContainerType.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferContainerType.java
@@ -30,6 +30,7 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.repo.policy.annotation.Behaviour;
import org.alfresco.repo.policy.annotation.BehaviourBean;
import org.alfresco.repo.policy.annotation.BehaviourKind;
@@ -45,31 +46,61 @@ import org.springframework.extensions.surf.util.I18NUtil;
*/
@BehaviourBean(defaultType = "rma:transferContainer")
public class TransferContainerType extends BaseBehaviourBean
- implements NodeServicePolicies.OnCreateChildAssociationPolicy, NodeServicePolicies.OnCreateNodePolicy
+ implements NodeServicePolicies.OnCreateChildAssociationPolicy,
+ NodeServicePolicies.OnCreateNodePolicy,
+ NodeServicePolicies.OnDeleteNodePolicy
{
private final static String MSG_ERROR_ADD_CONTENT_CONTAINER = "rm.service.error-add-content-container";
+ private final static String MSG_ERROR_ADD_CHILD_TO_TRANSFER_CONTAINER = "rm.action.create.transfer.container.child-error-message";
+ private static final String BEHAVIOUR_NAME = "onCreateChildAssocsForTransferContainer";
+ private static final String DELETE_BEHAVIOUR_NAME = "onDeleteTransferContainer";
/**
- * On every event
+ * Disable the behaviours for this transaction
+ */
+ public void disable()
+ {
+ getBehaviour(BEHAVIOUR_NAME).disable();
+ getBehaviour(DELETE_BEHAVIOUR_NAME).disable();
+ }
+
+ /**
+ * Enable behaviours for this transaction
+ */
+ public void enable()
+ {
+ getBehaviour(BEHAVIOUR_NAME).enable();
+ getBehaviour(DELETE_BEHAVIOUR_NAME).enable();
+ }
+
+ /**
+ * Prevent creating a node inside transfer container, this will be possible only through internal services in a controlled manner.
*
- * @see org.alfresco.repo.node.NodeServicePolicies.OnCreateChildAssociationPolicy#onCreateChildAssociation(org.alfresco.service.cmr.repository.ChildAssociationRef,
- * boolean)
+ * @see org.alfresco.repo.node.NodeServicePolicies.OnCreateChildAssociationPolicy#onCreateChildAssociation(org.alfresco.service.cmr.repository.ChildAssociationRef, * boolean)
*/
@Override
- @Behaviour(kind = BehaviourKind.ASSOCIATION)
+ @Behaviour(kind = BehaviourKind.ASSOCIATION,
+ name = BEHAVIOUR_NAME)
public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean bNew)
{
- // ensure not content to be added in Holdsfolder
- NodeRef nodeRef = childAssocRef.getChildRef();
- if (instanceOf(nodeRef, ContentModel.TYPE_CONTENT) == true) { throw new AlfrescoRuntimeException(
- I18NUtil.getMessage(MSG_ERROR_ADD_CONTENT_CONTAINER)); }
+ throw new IntegrityException(I18NUtil.getMessage(MSG_ERROR_ADD_CHILD_TO_TRANSFER_CONTAINER), null);
}
@Override
public void onCreateNode(ChildAssociationRef childAssocRef)
{
NodeRef nodeRef = childAssocRef.getChildRef();
- if (instanceOf(nodeRef, ContentModel.TYPE_CONTENT) == true) { throw new AlfrescoRuntimeException(
- I18NUtil.getMessage(MSG_ERROR_ADD_CONTENT_CONTAINER)); }
+ if (instanceOf(nodeRef, ContentModel.TYPE_CONTENT) == true)
+ {
+ throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_ERROR_ADD_CONTENT_CONTAINER));
+ }
+ }
+
+ @Override
+ @Behaviour(kind = BehaviourKind.CLASS,
+ name = DELETE_BEHAVIOUR_NAME)
+ public void onDeleteNode(ChildAssociationRef childAssocRef, boolean isNodeArchived)
+ {
+ throw new IntegrityException("Operation failed. Deletion of Transfer Container is not allowed.", null);
}
}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferType.java
new file mode 100644
index 0000000000..ba0989bab0
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferType.java
@@ -0,0 +1,79 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2017 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
+
+import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
+import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.node.integrity.IntegrityException;
+import org.alfresco.repo.policy.annotation.Behaviour;
+import org.alfresco.repo.policy.annotation.BehaviourBean;
+import org.alfresco.repo.policy.annotation.BehaviourKind;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.springframework.extensions.surf.util.I18NUtil;
+
+/**
+ * rma:transfer behaviour bean
+ *
+ * @author Silviu Dinuta
+ * @since 2.6
+ */
+@BehaviourBean(defaultType = "rma:transfer")
+public class TransferType extends BaseBehaviourBean
+ implements NodeServicePolicies.OnCreateChildAssociationPolicy
+{
+ private final static String MSG_ERROR_ADD_CHILD_TO_TRANSFER = "rm.action.create.transfer.child-error-message";
+
+ private static final String CREATE_CHILD_BEHAVIOUR_NAME = "onCreateChildAssocsForTransferType";
+
+ /**
+ * Disable the behaviours for this transaction
+ */
+ public void disable()
+ {
+ getBehaviour(CREATE_CHILD_BEHAVIOUR_NAME).disable();
+ }
+
+ /**
+ * Enable behaviours for this transaction
+ */
+ public void enable()
+ {
+ getBehaviour(CREATE_CHILD_BEHAVIOUR_NAME).enable();
+ }
+
+ /**
+ * Prevent creating a node inside transfer folder, this will be possible only through internal services in a controlled manner.
+ */
+ @Override
+ @Behaviour(kind = BehaviourKind.ASSOCIATION,
+ name = CREATE_CHILD_BEHAVIOUR_NAME)
+ public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNewNode)
+ {
+ throw new IntegrityException(I18NUtil.getMessage(MSG_ERROR_ADD_CHILD_TO_TRANSFER), null);
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/UnfiledRecordContainerType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/UnfiledRecordContainerType.java
new file mode 100644
index 0000000000..4c051465e4
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/UnfiledRecordContainerType.java
@@ -0,0 +1,97 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2017 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
+import org.alfresco.repo.node.NodeServicePolicies;
+import org.alfresco.repo.node.integrity.IntegrityException;
+import org.alfresco.repo.policy.annotation.Behaviour;
+import org.alfresco.repo.policy.annotation.BehaviourBean;
+import org.alfresco.repo.policy.annotation.BehaviourKind;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * rma:unfiledRecordContainer behaviour bean
+ *
+ * @author Silviu Dinuta
+ * @since 2.6
+ */
+@BehaviourBean(defaultType = "rma:unfiledRecordContainer")
+public class UnfiledRecordContainerType extends BaseBehaviourBean
+ implements NodeServicePolicies.OnCreateChildAssociationPolicy,
+ NodeServicePolicies.OnDeleteNodePolicy
+{
+ private static final String BEHAVIOUR_NAME = "onDeleteUnfiledRecordContainer";
+ private final static List ACCEPTED_NON_UNIQUE_CHILD_TYPES = Arrays.asList(TYPE_UNFILED_RECORD_FOLDER, ContentModel.TYPE_CONTENT, TYPE_NON_ELECTRONIC_DOCUMENT);
+
+ /**
+ * Disable the behaviours for this transaction
+ */
+ public void disable()
+ {
+ getBehaviour(BEHAVIOUR_NAME).disable();
+ }
+
+ /**
+ * Enable behaviours for this transaction
+ */
+ public void enable()
+ {
+ getBehaviour(BEHAVIOUR_NAME).enable();
+ }
+
+ @Override
+ @Behaviour(kind = BehaviourKind.ASSOCIATION)
+ public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNewNode)
+ {
+ // We need to automatically cast the created folder to record folder if it is a plain folder
+ // This occurs if the RM folder has been created via IMap, WebDav, etc. Don't check subtypes.
+ // Some modules use hidden folder subtypes to store information (see RM-3283).
+ QName childType = nodeService.getType(childAssocRef.getChildRef());
+ if (childType.equals(ContentModel.TYPE_FOLDER))
+ {
+ nodeService.setType(childAssocRef.getChildRef(), TYPE_UNFILED_RECORD_FOLDER);
+ }
+
+ // check the created child is of an accepted type
+ validateNewChildAssociationSubTypesIncluded(childAssocRef.getChildRef(), ACCEPTED_NON_UNIQUE_CHILD_TYPES);
+ }
+
+ @Override
+ @Behaviour(kind = BehaviourKind.CLASS,
+ name = BEHAVIOUR_NAME)
+ public void onDeleteNode(ChildAssociationRef childAssocRef, boolean isNodeArchived)
+ {
+ throw new IntegrityException("Operation failed. Deletion of Unfiled Record Container is not allowed.", null);
+ }
+}
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/UnfiledRecordFolderType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/UnfiledRecordFolderType.java
new file mode 100644
index 0000000000..51f4f62981
--- /dev/null
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/UnfiledRecordFolderType.java
@@ -0,0 +1,70 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2017 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 .
+ * #L%
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean;
+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.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.namespace.QName;
+
+/**
+ * rma:unfiledRecordFolder behaviour bean
+ *
+ * @author Silviu Dinuta
+ * @since 2.6
+ */
+@BehaviourBean(defaultType = "rma:unfiledRecordFolder")
+public class UnfiledRecordFolderType extends BaseBehaviourBean
+ implements NodeServicePolicies.OnCreateChildAssociationPolicy
+{
+ private final static List ACCEPTED_NON_UNIQUE_CHILD_TYPES = Arrays.asList(TYPE_UNFILED_RECORD_FOLDER, ContentModel.TYPE_CONTENT, TYPE_NON_ELECTRONIC_DOCUMENT);
+
+ @Override
+ @Behaviour(kind = BehaviourKind.ASSOCIATION)
+ public void onCreateChildAssociation(ChildAssociationRef childAssocRef, boolean isNewNode)
+ {
+ // We need to automatically cast the created folder to record folder if it is a plain folder
+ // This occurs if the RM folder has been created via IMap, WebDav, etc. Don't check subtypes.
+ // Some modules use hidden folder subtypes to store information (see RM-3283).
+ QName childType = nodeService.getType(childAssocRef.getChildRef());
+ if (childType.equals(ContentModel.TYPE_FOLDER))
+ {
+ nodeService.setType(childAssocRef.getChildRef(), TYPE_UNFILED_RECORD_FOLDER);
+ }
+
+ // check the created child is of an accepted type
+ validateNewChildAssociationSubTypesIncluded(childAssocRef.getChildRef(), ACCEPTED_NON_UNIQUE_CHILD_TYPES);
+ }
+}
diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/transfer/TransferServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/transfer/TransferServiceImpl.java
index ad25cb8239..652df3b6c5 100644
--- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/transfer/TransferServiceImpl.java
+++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/transfer/TransferServiceImpl.java
@@ -32,7 +32,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction;
@@ -41,6 +40,8 @@ import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.module.org_alfresco_module_rm.model.rma.type.TransferContainerType;
+import org.alfresco.module.org_alfresco_module_rm.model.rma.type.TransferType;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
@@ -87,6 +88,10 @@ public class TransferServiceImpl extends ServiceBaseImpl
/** Freeze Service */
protected FreezeService freezeService;
+ protected TransferContainerType transferContainerType;
+
+ protected TransferType transferType;
+
/**
* @param filePlanService file plan service
*/
@@ -127,6 +132,16 @@ public class TransferServiceImpl extends ServiceBaseImpl
this.freezeService = freezeService;
}
+ public void setTransferContainerType(TransferContainerType transferContainerType)
+ {
+ this.transferContainerType = transferContainerType;
+ }
+
+ public void setTransferType(TransferType transferType)
+ {
+ this.transferType = transferType;
+ }
+
/**
* @see org.alfresco.module.org_alfresco_module_rm.transfer.TransferService#transfer(NodeRef, boolean)
*/
@@ -164,11 +179,19 @@ public class TransferServiceImpl extends ServiceBaseImpl
}
NodeRef transferContainer = filePlanService.getTransferContainer(root);
- transferNodeRef = nodeService.createNode(transferContainer,
- ContentModel.ASSOC_CONTAINS,
- QName.createQName(RM_URI, transferName),
- TYPE_TRANSFER,
- transferProps).getChildRef();
+
+ transferContainerType.disable();
+ try
+ {
+ transferNodeRef = nodeService.createNode(transferContainer, ContentModel.ASSOC_CONTAINS,
+ QName.createQName(RM_URI, transferName), TYPE_TRANSFER, transferProps)
+ .getChildRef();
+
+ }
+ finally
+ {
+ transferContainerType.enable();
+ }
// Bind the hold node reference to the transaction
AlfrescoTransactionSupport.bindResource(KEY_TRANSFER_NODEREF, transferNodeRef);
@@ -188,13 +211,17 @@ public class TransferServiceImpl extends ServiceBaseImpl
}
// Link the record to the trasnfer object
- nodeService.addChild(transferNodeRef,
- nodeRef,
- ASSOC_TRANSFERRED,
- ASSOC_TRANSFERRED);
-
- // Set PDF indicator flag
- setPDFIndicationFlag(transferNodeRef, nodeRef);
+ transferType.disable();
+ try
+ {
+ nodeService.addChild(transferNodeRef, nodeRef, ASSOC_TRANSFERRED, ASSOC_TRANSFERRED);
+ // Set PDF indicator flag
+ setPDFIndicationFlag(transferNodeRef, nodeRef);
+ }
+ finally
+ {
+ transferType.enable();
+ }
// Set the transferring indicator aspect
nodeService.addAspect(nodeRef, ASPECT_TRANSFERRING, null);
@@ -253,12 +280,12 @@ public class TransferServiceImpl extends ServiceBaseImpl
{
throw new AlfrescoRuntimeException("Could not complete a transfer that contains held folders");
}
-
+
if(freezeService.hasFrozenChildren(assoc.getChildRef()))
{
throw new AlfrescoRuntimeException("Cound not complete a transfer that contains folders with held children");
}
-
+
markComplete(assoc.getChildRef(), accessionIndicator, transferLocation);
}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3341Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3341Test.java
index b954591d18..30e3c76578 100644
--- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3341Test.java
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM3341Test.java
@@ -25,16 +25,15 @@
* #L%
*
*/
+
package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
-import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
-import org.alfresco.service.cmr.model.FileInfo;
+import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AccessStatus;
-import org.springframework.extensions.surf.util.I18NUtil;
/**
* Unit test for RM-3341 .. can copy to hold and transfer folder
@@ -43,9 +42,6 @@ import org.springframework.extensions.surf.util.I18NUtil;
*/
public class RM3341Test extends BaseRMTestCase
{
-
- private final static String MSG_ERROR_ADD_CONTENT_CONTAINER = "rm.service.error-add-content-container";
-
public void testCopyingContentsInHoldandTransfer() throws Exception
{
doTestInTransaction(new Test()
@@ -59,9 +55,9 @@ public class RM3341Test extends BaseRMTestCase
assertNotNull(transferContainer);
assertEquals(AccessStatus.ALLOWED,
- permissionService.hasPermission(holdContainer, RMPermissionModel.FILING));
+ permissionService.hasPermission(holdContainer, RMPermissionModel.FILING));
assertEquals(AccessStatus.ALLOWED,
- permissionService.hasPermission(transferContainer, RMPermissionModel.FILING));
+ permissionService.hasPermission(transferContainer, RMPermissionModel.FILING));
return null;
}
@@ -79,13 +75,12 @@ public class RM3341Test extends BaseRMTestCase
try
{
- FileInfo copyInfo = fileFolderService.create(holdContainer, "test file", ContentModel.TYPE_CONTENT);
+ fileFolderService.create(holdContainer, "test file", ContentModel.TYPE_CONTENT);
fail("This should have thrown an exception");
}
- catch (AlfrescoRuntimeException e)
+ catch (IntegrityException e)
{
- // ("Content can't be added to a record container. Use record folders to file content.")
- assertEquals(I18NUtil.getMessage(MSG_ERROR_ADD_CONTENT_CONTAINER), e.getMsgId());
+ // ("Content can't be added to a hold container. Use record folders to file content.")
}
return null;
}
@@ -109,10 +104,9 @@ public class RM3341Test extends BaseRMTestCase
fail("This should have thrown an exception");
}
- catch (AlfrescoRuntimeException e)
+ catch (IntegrityException e)
{
- // ("Content can't be added to a record container. Use record folders to file content.")
- assertEquals(I18NUtil.getMessage(MSG_ERROR_ADD_CONTENT_CONTAINER), e.getMsgId());
+ // ("Content can't be added to a transfer container. Use record folders to file content.")
}
return null;
}
diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4293Test.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4293Test.java
new file mode 100644
index 0000000000..d39fbadcd8
--- /dev/null
+++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4293Test.java
@@ -0,0 +1,125 @@
+/*
+ * #%L
+ * Alfresco Records Management Module
+ * %%
+ * Copyright (C) 2005 - 2017 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 .
+ * #L%
+ *
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.test.integration.issue;
+
+import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
+import org.alfresco.repo.node.integrity.IntegrityException;
+import org.alfresco.service.cmr.repository.NodeRef;
+
+/**
+ * Test for RM-4293
+ *
+ * @author Silviu Dinuta
+ * @since 2.6
+ */
+public class RM4293Test extends BaseRMTestCase
+{
+ public void testDeleteSpecialContainers() throws Exception
+ {
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ NodeRef holdContainer = filePlanService.getHoldContainer(filePlan);
+ assertNotNull(holdContainer);
+
+ try
+ {
+ fileFolderService.delete(holdContainer);
+ fail("This should have thrown an exception");
+ }
+ catch (IntegrityException e)
+ {
+ // ("Hold Container can't be deleted.")
+ }
+ return null;
+ }
+ });
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ NodeRef transferContainer = filePlanService.getTransferContainer(filePlan);
+ assertNotNull(transferContainer);
+ try
+ {
+ fileFolderService.delete(transferContainer);
+ fail("This should have thrown an exception");
+ }
+ catch (IntegrityException e)
+ {
+ // ("Transfer Container can't be deleted.")
+ }
+ return null;
+ }
+ });
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ NodeRef unfiledRecordContainer = filePlanService.getUnfiledContainer(filePlan);
+ assertNotNull(unfiledRecordContainer);
+
+ try
+ {
+ fileFolderService.delete(unfiledRecordContainer);
+ fail("This should have thrown an exception");
+ }
+ catch (IntegrityException e)
+ {
+ // ("Unfiled Record Container can't be deleted.")
+ }
+ return null;
+ }
+ });
+
+ doTestInTransaction(new Test()
+ {
+ @Override
+ public Void run()
+ {
+ try
+ {
+ fileFolderService.delete(filePlan);
+ fail("This should have thrown an exception");
+ }
+ catch (IntegrityException e)
+ {
+ // ("FilePlan can't be deleted.")
+ }
+ return null;
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferContainerTypeUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferContainerTypeUnitTest.java
index 2414556d3d..e797308c3e 100644
--- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferContainerTypeUnitTest.java
+++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/model/rma/type/TransferContainerTypeUnitTest.java
@@ -26,11 +26,16 @@
*/
package org.alfresco.module.org_alfresco_module_rm.model.rma.type;
-import org.alfresco.error.AlfrescoRuntimeException;
-import org.alfresco.model.ContentModel;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
+import org.alfresco.repo.node.integrity.IntegrityException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.namespace.QName;
import org.junit.Test;
import org.mockito.InjectMocks;
@@ -42,40 +47,27 @@ import org.mockito.InjectMocks;
*/
public class TransferContainerTypeUnitTest extends BaseUnitTest
{
- /** test object */
- private @InjectMocks TransferContainerType transferContainerType;
+ /**
+ * test object
+ */
+ private @InjectMocks
+ TransferContainerType transferContainerType;
/**
- * Having the Unfilled Record container and a folder having the aspect ASPECT_HIDDEN When adding a child association
- * between the folder and the container Then the folder type shouldn't be renamed
+ * Given that we try to add to transfer container,
+ * Then IntegrityException is thrown.
*/
- @Test(expected = AlfrescoRuntimeException.class)
- public void testAddContentToTransferContainerTest()
+ @Test(expected = IntegrityException.class)
+ public void testAddToTransferContainerTest()
{
+ NodeRef transferContainer = generateNodeRef(TYPE_TRANSFER_CONTAINER, true);
- NodeRef transferContainer = createTransferContainer();
-
- /*
- * When adding a child association between the folder and the container
- */
- NodeRef record = generateNodeRef(ContentModel.TYPE_CONTENT);
- ChildAssociationRef childAssoc = new ChildAssociationRef(ContentModel.TYPE_CONTENT, transferContainer,
- ContentModel.TYPE_CONTENT, record);
-
- transferContainerType.onCreateChildAssociation(childAssoc, true);
+ QName type = AlfMock.generateQName();
+ NodeRef nodeRef = AlfMock.generateNodeRef(mockedNodeService, type);
+ ChildAssociationRef mockedChildAssoc = mock(ChildAssociationRef.class);
+ when(mockedChildAssoc.getChildRef()).thenReturn(nodeRef);
+ when(mockedChildAssoc.getParentRef()).thenReturn(transferContainer);
+ transferContainerType.onCreateChildAssociation(mockedChildAssoc, true);
}
-
- /**
- * Generates a record management container
- *
- * @return reference to the generated container
- */
- private NodeRef createTransferContainer()
- {
- NodeRef holdContainer = generateNodeRef(TYPE_TRANSFER, true);
-
- return holdContainer;
- }
-
}