From 57b3460b58b7e60cce5126ce2783b698f3119da8 Mon Sep 17 00:00:00 2001 From: Sara Aspery Date: Tue, 20 Jun 2017 11:12:22 +0100 Subject: [PATCH] include_declare_record_refactoring_in_Rest --- .../rm-action-context.xml | 3 +- .../rm-service-context.xml | 1984 +++++++++-------- .../action/impl/DeclareRecordAction.java | 225 +- .../record/RecordService.java | 380 ++-- .../record/RecordServiceImpl.java | 718 +++--- .../record/CompleteRecordTest.java | 34 +- 6 files changed, 1669 insertions(+), 1675 deletions(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml index 73adaab087..9d658f65cc 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml @@ -388,8 +388,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 c2fd343d4b..2a9b9accf5 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 @@ -1,10 +1,10 @@ - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - + + + + + + + - + - + - + - - - + + + - - - org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - - - - - - - - - + + + + + + + + + - - - org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService - - - - - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService + + + + + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - - - - - - - - - - - + + + + + + + + + + + - - - org.alfresco.module.org_alfresco_module_rm.transfer.TransferService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.transfer.TransferService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - + + - - - org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - - - - - + + + + + + + - - - + + + - - - org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.search.RecordsManagementSearchService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - + class="org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanServiceImpl"> + + - - - org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService - - - - - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService + + + + + + + + + + + + + + + + - + - - - - + + + - - - + + + - - - - - - - - + class="org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionServiceImpl" + init-method="init"> + + + + + + + + - - - org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - - - - - + + + + + + + + - + - - - org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - - - - - + + + + + + + + - - - org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService + + + + + + + + + + + + - + - - - - + + + - - - + + + - + - - - - - + + + + + - - - org.alfresco.module.org_alfresco_module_rm.model.security.ModelSecurityService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.model.security.ModelSecurityService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - + + + + - - - org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - + + + + - - - org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - - - - - - + + + + + + - + - + rma:recordCategory @@ -798,38 +817,39 @@ - - - org.alfresco.module.org_alfresco_module_rm.admin.RecordsManagementAdminService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.admin.RecordsManagementAdminService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - - - + + + + + + - - - org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - - - - - - - - - - - - cm:lastThumbnailModification - cm:autoVersion - cm:autoVersionOnUpdateProps - cm:initialVersion - - - + + + + + + + + + + + + + + + cm:lastThumbnailModification + cm:autoVersion + cm:autoVersionOnUpdateProps + cm:initialVersion + + + - - - org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - - - - + + + + + + + - - - org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1090,46 +1118,48 @@ http://www.alfresco.org/model/rendition/1.0 - - - - + + + + - - - org.alfresco.module.org_alfresco_module_rm.record.RecordService - - - - - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.record.RecordService + + + + + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - + @@ -1173,22 +1205,23 @@ - + - - - + + + - + - + @@ -1211,25 +1244,25 @@ + class="org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationServiceImpl" /> org.alfresco.module.org_alfresco_module_rm.security.FilePlanAuthenticationService - + - - - + + + - + @@ -1241,16 +1274,18 @@ - - + + - + - + + + Thread-Index @@ -1263,110 +1298,112 @@ - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - - - - org.alfresco.module.org_alfresco_module_rm.email.CustomEmailMappingService - - - - customEmailMappingService - - - - - - - - - + + + + org.alfresco.module.org_alfresco_module_rm.email.CustomEmailMappingService + + + + customEmailMappingService + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - + - - - - - - + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - + - + - + - - - - - - org.alfresco.caveatConfigTransactionalCache - - - - - + + + + + + org.alfresco.caveatConfigTransactionalCache + + + + + - + {http://www.alfresco.org/model/recordsmanagement/1.0}recordComponentIdentifier @@ -1374,7 +1411,7 @@ - + {http://www.alfresco.org/model/rmcustom/1.0}rmcustom @@ -1382,14 +1419,15 @@ - - - + + + - - - - + + + - - - + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigService - - - - caveatConfigService - - - - - - - - - + + + + org.alfresco.module.org_alfresco_module_rm.caveat.RMCaveatConfigService + + + + caveatConfigService + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - org.alfresco.module.org_alfresco_module_rm.dataset.DataSetService - - - - - - - - - - - - + + + org.alfresco.module.org_alfresco_module_rm.dataset.DataSetService + + + + + + + + + + + + - - - - - - - ${server.transaction.mode.default} - - - + + + + + + + ${server.transaction.mode.default} + + + - - - - + + + - - - + + + - + - - - + + + - - - - + + + + @@ -1526,7 +1567,7 @@ - + @@ -1536,13 +1577,13 @@ org.alfresco.module.org_alfresco_module_rm.hold.HoldService - + - - - + + + @@ -1575,8 +1616,10 @@ - - + + @@ -1584,20 +1627,21 @@ org.alfresco.module.org_alfresco_module_rm.relationship.RelationshipService - + - - - + + + - + - + @@ -1628,8 +1672,9 @@ - - + + @@ -1637,20 +1682,21 @@ org.alfresco.module.org_alfresco_module_rm.recordableversion.RecordableVersionConfigService - + - - - + + + - + - + diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DeclareRecordAction.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DeclareRecordAction.java index 180ef6b895..fe21ae45cd 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DeclareRecordAction.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DeclareRecordAction.java @@ -27,33 +27,13 @@ package org.alfresco.module.org_alfresco_module_rm.action.impl; -import static org.alfresco.module.org_alfresco_module_rm.record.RecordUtils.generateRecordIdentifier; - -import java.io.Serializable; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase; -import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImpl; -import org.alfresco.module.org_alfresco_module_rm.util.TransactionalResourceHelper; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.node.integrity.IntegrityException; import org.alfresco.service.cmr.action.Action; -import org.alfresco.service.cmr.dictionary.AspectDefinition; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.security.OwnableService; -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; +import org.alfresco.util.ParameterCheck; /** * Declare record action @@ -62,36 +42,24 @@ import org.springframework.extensions.surf.util.I18NUtil; */ public class DeclareRecordAction extends RMActionExecuterAbstractBase { - /** action name */ + /** + * action name + */ public static final String NAME = "declareRecord"; - /** I18N */ - private static final String MSG_UNDECLARED_ONLY_RECORDS = "rm.action.undeclared-only-records"; - private static final String MSG_NO_DECLARE_MAND_PROP = "rm.action.no-declare-mand-prop"; - - /** Logger */ - private static Log logger = LogFactory.getLog(DeclareRecordAction.class); - - /** check mandatory properties */ - private boolean checkMandatoryPropertiesEnabled = true; - - /** transactional resource helper */ - private TransactionalResourceHelper transactionalResourceHelper; + /** + * Record service + */ + private RecordService recordService; /** - * @param checkMandatoryPropertiesEnabled true if check mandatory properties is enabled, false otherwise + * Sets the record service + * + * @param recordService record service */ - public void setCheckMandatoryPropertiesEnabled(boolean checkMandatoryPropertiesEnabled) + public void setRecordService(RecordService recordService) { - this.checkMandatoryPropertiesEnabled = checkMandatoryPropertiesEnabled; - } - - /** - * @param transactionalResourceHelper - */ - public void setTransactionalResourceHelper(TransactionalResourceHelper transactionalResourceHelper) - { - this.transactionalResourceHelper = transactionalResourceHelper; + this.recordService = recordService; } /** @@ -100,167 +68,14 @@ public class DeclareRecordAction extends RMActionExecuterAbstractBase @Override protected void executeImpl(final Action action, final NodeRef actionedUponNodeRef) { - if (getNodeService().exists(actionedUponNodeRef) && - getRecordService().isRecord(actionedUponNodeRef) && - !getFreezeService().isFrozen(actionedUponNodeRef)) + ParameterCheck.mandatory("actionedUponNodeRef", actionedUponNodeRef); + try { - if (!getRecordService().isDeclared(actionedUponNodeRef)) - { - // if the record is newly created make sure the record identifier is set before completing the record - Set newRecords = transactionalResourceHelper.getSet(RecordServiceImpl.KEY_NEW_RECORDS); - if(newRecords.contains(actionedUponNodeRef)) - { - generateRecordIdentifier(getNodeService(), getIdentifierService(), actionedUponNodeRef); - } - - List missingProperties = new ArrayList<>(5); - // Aspect not already defined - check mandatory properties then add - if (!checkMandatoryPropertiesEnabled || - mandatoryPropertiesSet(actionedUponNodeRef, missingProperties)) - { - getRecordService().disablePropertyEditableCheck(); - try - { - // Add the declared aspect - Map declaredProps = new HashMap<>(2); - declaredProps.put(PROP_DECLARED_AT, new Date()); - declaredProps.put(PROP_DECLARED_BY, AuthenticationUtil.getRunAsUser()); - this.getNodeService().addAspect(actionedUponNodeRef, ASPECT_DECLARED_RECORD, declaredProps); - - AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public Void doWork() - { - // remove all owner related rights - getOwnableService().setOwner(actionedUponNodeRef, OwnableService.NO_OWNER); - return null; - } - }); - } - finally - { - getRecordService().enablePropertyEditableCheck(); - } - } - else - { - logger.debug(buildMissingPropertiesErrorString(missingProperties)); - action.setParameterValue(ActionExecuterAbstractBase.PARAM_RESULT, "missingProperties"); - } - } - } - else + recordService.complete(actionedUponNodeRef); + } catch (IntegrityException e) { - if (logger.isWarnEnabled()) - { - logger.warn(I18NUtil.getMessage(MSG_UNDECLARED_ONLY_RECORDS, actionedUponNodeRef.toString())); - } - } - } - - private String buildMissingPropertiesErrorString(List missingProperties) - { - StringBuilder builder = new StringBuilder(255); - builder.append(I18NUtil.getMessage(MSG_NO_DECLARE_MAND_PROP)); - builder.append(" "); - for (String missingProperty : missingProperties) - { - builder.append(missingProperty).append(", "); - } - return builder.toString(); - } - - /** - * Helper method to check whether all the mandatory properties of the node have been set - * - * @param nodeRef node reference - * @return boolean true if all mandatory properties are set, false otherwise - */ - private boolean mandatoryPropertiesSet(NodeRef nodeRef, List missingProperties) - { - boolean result = true; - - Map nodeRefProps = this.getNodeService().getProperties(nodeRef); - - QName nodeRefType = this.getNodeService().getType(nodeRef); - - TypeDefinition typeDef = this.getDictionaryService().getType(nodeRefType); - for (PropertyDefinition propDef : typeDef.getProperties().values()) - { - if (propDef.isMandatory() && nodeRefProps.get(propDef.getName()) == null) - { - logMissingProperty(propDef, missingProperties); - - result = false; - break; - } + action.setParameterValue(ActionExecuterAbstractBase.PARAM_RESULT, e.getMessage()); } - if (result) - { - Set aspects = this.getNodeService().getAspects(nodeRef); - for (QName aspect : aspects) - { - AspectDefinition aspectDef = this.getDictionaryService().getAspect(aspect); - for (PropertyDefinition propDef : aspectDef.getProperties().values()) - { - if (propDef.isMandatory() && nodeRefProps.get(propDef.getName()) == null) - { - logMissingProperty(propDef, missingProperties); - - result = false; - break; - } - } - } - } - - // check for missing mandatory metadata from custom aspect definitions - if (result) - { - QName aspect = ASPECT_RECORD; - if (nodeRefType.equals(TYPE_NON_ELECTRONIC_DOCUMENT)) - { - aspect = TYPE_NON_ELECTRONIC_DOCUMENT; - } - - // get customAspectImpl - String localName = aspect.toPrefixString(getNamespaceService()).replace(":", ""); - localName = MessageFormat.format("{0}CustomProperties", localName); - QName customAspect = QName.createQName(RM_CUSTOM_URI, localName); - - AspectDefinition aspectDef = this.getDictionaryService().getAspect(customAspect); - - for (PropertyDefinition propDef : aspectDef.getProperties().values()) - { - if (propDef.isMandatory() && nodeRefProps.get(propDef.getName()) == null) - { - logMissingProperty(propDef, missingProperties); - - result = false; - break; - } - } - } - - return result; - } - - /** - * Log information about missing properties. - * - * @param propDef property definition - * @param missingProperties missing properties - */ - private void logMissingProperty(PropertyDefinition propDef, List missingProperties) - { - if (logger.isWarnEnabled()) - { - StringBuilder msg = new StringBuilder(); - msg.append("Mandatory property missing: ").append(propDef.getName()); - logger.warn(msg.toString()); - } - missingProperties.add(propDef.getName().toString()); } } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java index e7e7a16ab1..f9cfaf2255 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java @@ -55,9 +55,8 @@ public interface RecordService * A record metadata aspect can be registered more than once if it applies to more than one * file plan type. * - * @param recordMetadataAspect record metadata aspect qualified name - * @param filePlanType file plan type - * + * @param recordMetadataAspect record metadata aspect qualified name + * @param filePlanType file plan type * @since 2.2 */ void registerRecordMetadataAspect(QName recordMetadataAspect, QName filePlanType); @@ -72,8 +71,7 @@ public interface RecordService /** * Disables the property editable check for a given node in this transaction only. * - * @param nodeRef node reference - * + * @param nodeRef node reference * @since 2.2 */ void disablePropertyEditableCheck(NodeRef nodeRef); @@ -84,213 +82,199 @@ public interface RecordService void enablePropertyEditableCheck(); /** - * Gets a list of all the record meta-data aspects - * - * @return {@link Set}<{@link QName}> list of record meta-data aspects - * - * @deprecated since 2.2, file plan component required to provide context - */ - @Deprecated - Set getRecordMetaDataAspects(); - - /** - * Indicates whether the provided aspect is a registered record meta-data - * aspect. - * - * @param aspect aspect {@link QName} - * @return boolean true if the aspect is a registered record meta-data aspect, false otherwise - * - * @since 2.3 - */ - boolean isRecordMetadataAspect(QName aspect); - - /** - * Indicates whther the provided property is declared on a registered record - * meta-data aspect. - * - * @param property property {@link QName} - * @return boolean true if the property is declared on a registered record meta-data aspect, - * false otherwise - * - * @since 2.3 - */ - boolean isRecordMetadataProperty(QName property); - - /** - * Gets a list of all the record metadata aspects relevant to the file plan type of the - * file plan component provided. - *

- * If a null context is provided all record meta-data aspects are returned, but this is not - * recommended. - * - * @param nodeRef node reference to file plan component providing context - * @return {@link Set}<{@link QName}> list of record meta-data aspects - * - * @since 2.2 - */ - Set getRecordMetadataAspects(NodeRef nodeRef); - - /** - * Gets a list of all the record metadata aspect that relate to the provided file plan type. - *

- * If null is provided for the file plan type then record metadata aspects for the default - * file plan type (rma:filePlan) are returned. - * - * @param filePlanType file plan type - * @return{@link Set}<{@link QName}> list of record meta-data aspects - * - * @since 2.2 - */ - Set getRecordMetadataAspects(QName filePlanType); - - /** - * Checks whether if the given node reference is a record or not - * - * @param nodeRef node reference to be checked - * @return boolean true if the node reference is a record, false otherwise - */ - boolean isRecord(NodeRef nodeRef); - - /** - * Indicates whether the record is declared - * - * @param nodeRef node reference of the record for which the check would be performed - * @return boolean true if record is declared, false otherwise - */ - boolean isDeclared(NodeRef nodeRef); - - /** - * Creates a new unfiled record from an existing node. - *

- * Note that the node reference of the record will be the same as the original - * document. - * - * @param filePlan The filePlan in which the record should be placed. filePlan can be null in this case the default RM site will be used. - * @param nodeRef The node from which the record will be created - * @param isLinked indicates if the newly created record is linked to it's original location or not. - */ - void createRecord(NodeRef filePlan, NodeRef nodeRef, boolean isLinked); - - /** - * Links the newly created record to it's original location. - * - * @see #createRecord(NodeRef, NodeRef, boolean) - */ - void createRecord(NodeRef filePlan, NodeRef nodeRef); - - /** - * Creates a record from a copy of the node reference provided. - * - * @param filePlan file plan - * @param nodeRef node reference - */ - NodeRef createRecordFromCopy(NodeRef filePlan, NodeRef nodeRef); - - /** - * Creates a new document in the unfiled records container if the given node reference is a file plan - * node reference otherwise the node reference will be used as the destination for the new record. - * - * @param parent parent node reference - * @param name name of the new record - * @param type content type, cm:content if null - * @param properties properties - * @param reader content reader - */ - NodeRef createRecordFromContent(NodeRef parent, String name, QName type, Map properties, ContentReader reader); - - /** - * Indicates whether the record is filed or not - * - * @param nodeRef record - * @return boolean true if filed, false otherwise - */ - boolean isFiled(NodeRef record); - - /** - * 'File' a new document that arrived in the file plan structure. - * - * @param nodeRef record - */ - void file(NodeRef record); + * Gets a list of all the record meta-data aspects + * + * @return {@link Set}<{@link QName}> list of record meta-data aspects + * @deprecated since 2.2, file plan component required to provide context + */ + @Deprecated + Set getRecordMetaDataAspects(); /** - * Indicates whether all the mandatory metadata for the record is populated or not + * Indicates whether the provided aspect is a registered record meta-data + * aspect. * - * @param record record for which to check if all mandatory metadata is populated - * @return boolean true if all mandatory metadata is populated, false otherwise + * @param aspect aspect {@link QName} + * @return boolean true if the aspect is a registered record meta-data aspect, false otherwise + * @since 2.3 */ - boolean isMandatoryPropertiesPopulated(NodeRef record); + boolean isRecordMetadataAspect(QName aspect); /** - * Completes a record. + * Indicates whther the provided property is declared on a registered record + * meta-data aspect. * - * @param record record to be completed + * @param property property {@link QName} + * @return boolean true if the property is declared on a registered record meta-data aspect, + * false otherwise + * @since 2.3 */ - void complete(NodeRef record); + boolean isRecordMetadataProperty(QName property); - /** - * Rejects a record with the provided reason - * - * @param nodeRef The record which will be rejected - * @param reason The reason for rejection - */ - void rejectRecord(NodeRef nodeRef, String reason); + /** + * Gets a list of all the record metadata aspects relevant to the file plan type of the + * file plan component provided. + *

+ * If a null context is provided all record meta-data aspects are returned, but this is not + * recommended. + * + * @param nodeRef node reference to file plan component providing context + * @return {@link Set}<{@link QName}> list of record meta-data aspects + * @since 2.2 + */ + Set getRecordMetadataAspects(NodeRef nodeRef); - /** - * Indicates whether a property of a record is editable for the current user or not. - * - * @param record record - * @param property property - * @return boolean true if editable, false otherwise. - */ - boolean isPropertyEditable(NodeRef record, QName property); + /** + * Gets a list of all the record metadata aspect that relate to the provided file plan type. + *

+ * If null is provided for the file plan type then record metadata aspects for the default + * file plan type (rma:filePlan) are returned. + * + * @param filePlanType file plan type + * @return{@link Set}<{@link QName}> list of record meta-data aspects + * @since 2.2 + */ + Set getRecordMetadataAspects(QName filePlanType); - /** - * Indicates whether the given node (record or record folder) is a metadata stub or not. - * - * @param nodeRef node reference - * @return boolean true if a metadata stub, false otherwise - */ - boolean isMetadataStub(NodeRef nodeRef); + /** + * Checks whether if the given node reference is a record or not + * + * @param nodeRef node reference to be checked + * @return boolean true if the node reference is a record, false otherwise + */ + boolean isRecord(NodeRef nodeRef); - /** - * Gets a list of all the records within a record folder - * - * @param recordFolder record folder - * @return List list of records in the record folder - */ - List getRecords(NodeRef recordFolder); + /** + * Indicates whether the record is declared + * + * @param nodeRef node reference of the record for which the check would be performed + * @return boolean true if record is declared, false otherwise + */ + boolean isDeclared(NodeRef nodeRef); - /** - * Adds the specified type to the record - * - * @param nodeRef Record node reference - * @param typeQName Type to add - */ - void addRecordType(NodeRef nodeRef, QName typeQName); + /** + * Creates a new unfiled record from an existing node. + *

+ * Note that the node reference of the record will be the same as the original + * document. + * + * @param filePlan The filePlan in which the record should be placed. filePlan can be null in this case the default RM site will be used. + * @param nodeRef The node from which the record will be created + * @param isLinked indicates if the newly created record is linked to it's original location or not. + */ + void createRecord(NodeRef filePlan, NodeRef nodeRef, boolean isLinked); - /** - * Creates a record from the given document - * - * @param nodeRef The document node reference from which a record will be created - */ - void makeRecord(NodeRef nodeRef); + /** + * Links the newly created record to it's original location. + * + * @see #createRecord(NodeRef, NodeRef, boolean) + */ + void createRecord(NodeRef filePlan, NodeRef nodeRef); - /** - * Links a record to a record folder - * - * @param record the record to link - * @param recordFolder the record folder to link it to - */ - void link(NodeRef record, NodeRef recordFolder); + /** + * Creates a record from a copy of the node reference provided. + * + * @param filePlan file plan + * @param nodeRef node reference + */ + NodeRef createRecordFromCopy(NodeRef filePlan, NodeRef nodeRef); - /** - * Unlinks a record from a specified record folder. - * - * @param record the record to unlink - * @param recordFolder the record folder to unlink it from - * - * @since 2.3 - */ - void unlink(NodeRef record, NodeRef recordFolder); + /** + * Creates a new document in the unfiled records container if the given node reference is a file plan + * node reference otherwise the node reference will be used as the destination for the new record. + * + * @param parent parent node reference + * @param name name of the new record + * @param type content type, cm:content if null + * @param properties properties + * @param reader content reader + */ + NodeRef createRecordFromContent(NodeRef parent, String name, QName type, Map properties, ContentReader reader); + + /** + * Indicates whether the record is filed or not + * + * @param record Record node reference + * @return boolean true if filed, false otherwise + */ + boolean isFiled(NodeRef record); + + /** + * 'File' a new document that arrived in the file plan structure. + * + * @param record Record node reference + */ + void file(NodeRef record); + + /** + * Rejects a record with the provided reason + * + * @param nodeRef The record which will be rejected + * @param reason The reason for rejection + */ + void rejectRecord(NodeRef nodeRef, String reason); + + /** + * Indicates whether a property of a record is editable for the current user or not. + * + * @param record record + * @param property property + * @return boolean true if editable, false otherwise. + */ + boolean isPropertyEditable(NodeRef record, QName property); + + /** + * Indicates whether the given node (record or record folder) is a metadata stub or not. + * + * @param nodeRef node reference + * @return boolean true if a metadata stub, false otherwise + */ + boolean isMetadataStub(NodeRef nodeRef); + + /** + * Gets a list of all the records within a record folder + * + * @param recordFolder record folder + * @return List list of records in the record folder + */ + List getRecords(NodeRef recordFolder); + + /** + * Adds the specified type to the record + * + * @param nodeRef Record node reference + * @param typeQName Type to add + */ + void addRecordType(NodeRef nodeRef, QName typeQName); + + /** + * Creates a record from the given document + * + * @param nodeRef The document node reference from which a record will be created + */ + void makeRecord(NodeRef nodeRef); + + /** + * Links a record to a record folder + * + * @param record the record to link + * @param recordFolder the record folder to link it to + */ + void link(NodeRef record, NodeRef recordFolder); + + /** + * Unlinks a record from a specified record folder. + * + * @param record the record to unlink + * @param recordFolder the record folder to unlink it from + * @since 2.3 + */ + void unlink(NodeRef record, NodeRef recordFolder); + + /** + * Completes a record + * + * @param nodeRef Record node reference + */ + void complete(NodeRef nodeRef); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java index 040768700e..fc9b8af4b3 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java @@ -34,6 +34,7 @@ import static org.alfresco.repo.policy.Behaviour.NotificationFrequency.TRANSACTI import static org.alfresco.repo.policy.annotation.BehaviourKind.ASSOCIATION; import java.io.Serializable; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -62,6 +63,7 @@ import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedul import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model; 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.identifier.IdentifierService; import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementCustomModel; @@ -82,9 +84,9 @@ import org.alfresco.repo.content.ContentServicePolicies; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.node.integrity.IncompleteNodeTagger; import org.alfresco.repo.node.integrity.IntegrityException; +import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.policy.ClassPolicyDelegate; import org.alfresco.repo.policy.PolicyComponent; -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; @@ -134,42 +136,63 @@ import org.springframework.extensions.surf.util.I18NUtil; */ @BehaviourBean public class RecordServiceImpl extends BaseBehaviourBean - implements RecordService, - RecordsManagementModel, - RecordsManagementCustomModel, - NodeServicePolicies.OnAddAspectPolicy, - NodeServicePolicies.OnCreateChildAssociationPolicy, - NodeServicePolicies.OnRemoveAspectPolicy, - NodeServicePolicies.OnUpdatePropertiesPolicy, - ContentServicePolicies.OnContentUpdatePolicy + implements RecordService, + RecordsManagementModel, + RecordsManagementCustomModel, + NodeServicePolicies.OnAddAspectPolicy, + NodeServicePolicies.OnCreateChildAssociationPolicy, + NodeServicePolicies.OnRemoveAspectPolicy, + NodeServicePolicies.OnUpdatePropertiesPolicy, + ContentServicePolicies.OnContentUpdatePolicy { - /** Logger */ + /** + * Logger + */ private static final Logger LOGGER = LoggerFactory.getLogger(RecordServiceImpl.class); - /** Sync Model URI */ + /** + * Sync Model URI + */ private static final String SYNC_MODEL_1_0_URI = "http://www.alfresco.org/model/sync/1.0"; - /** Synced aspect */ + /** + * Synced aspect + */ private static final QName ASPECT_SYNCED = QName.createQName(SYNC_MODEL_1_0_URI, "synced"); - /** transation data key */ + /** + * transation data key + */ private static final String KEY_IGNORE_ON_UPDATE = "ignoreOnUpdate"; public static final String KEY_NEW_RECORDS = "newRecords"; - /** I18N */ + /** + * I18N + */ private static final String MSG_NODE_HAS_ASPECT = "rm.service.node-has-aspect"; private static final String FINAL_VERSION = "rm.service.final-version"; private static final String FINAL_DESCRIPTION = "rm.service.final-version-description"; + private static final String MSG_UNDECLARED_ONLY_RECORDS = "rm.action.undeclared-only-records"; + private static final String MSG_NO_DECLARE_MAND_PROP = "rm.action.no-declare-mand-prop"; - /** Always edit property array */ + /** + * Always edit property array + */ private static final QName[] ALWAYS_EDIT_PROPERTIES = new QName[] - { - ContentModel.PROP_LAST_THUMBNAIL_MODIFICATION_DATA - }; + { + ContentModel.PROP_LAST_THUMBNAIL_MODIFICATION_DATA + }; - /** always edit model URI's */ + /** + * always edit model URI's + */ private List alwaysEditURIs; + /** + * check mandatory properties + */ + private boolean checkMandatoryPropertiesEnabled = true; + /** * @param alwaysEditURIs the alwaysEditURIs to set */ @@ -186,86 +209,140 @@ public class RecordServiceImpl extends BaseBehaviourBean return this.alwaysEditURIs; } - /** record model URI's */ + /** + * record model URI's + */ public static final List RECORD_MODEL_URIS = Collections.unmodifiableList( - Arrays.asList( - RM_URI, - RM_CUSTOM_URI, - ReportModel.RMR_URI, - RecordableVersionModel.RMV_URI, - DOD5015Model.DOD_URI - )); + Arrays.asList( + RM_URI, + RM_CUSTOM_URI, + ReportModel.RMR_URI, + RecordableVersionModel.RMV_URI, + DOD5015Model.DOD_URI + )); - /** non-record model URI's */ + /** + * non-record model URI's + */ private static final String[] NON_RECORD_MODEL_URIS = new String[] - { - NamespaceService.AUDIO_MODEL_1_0_URI, - NamespaceService.CONTENT_MODEL_1_0_URI, - NamespaceService.EMAILSERVER_MODEL_URI, - NamespaceService.EXIF_MODEL_1_0_URI, - NamespaceService.FORUMS_MODEL_1_0_URI, - NamespaceService.LINKS_MODEL_1_0_URI, - NamespaceService.REPOSITORY_VIEW_1_0_URI - }; + { + NamespaceService.AUDIO_MODEL_1_0_URI, + NamespaceService.CONTENT_MODEL_1_0_URI, + NamespaceService.EMAILSERVER_MODEL_URI, + NamespaceService.EXIF_MODEL_1_0_URI, + NamespaceService.FORUMS_MODEL_1_0_URI, + NamespaceService.LINKS_MODEL_1_0_URI, + NamespaceService.REPOSITORY_VIEW_1_0_URI + }; - /** Indentity service */ + /** + * Indentity service + */ private IdentifierService identifierService; - /** Extended permission service */ + /** + * Extended permission service + */ private ExtendedPermissionService extendedPermissionService; - /** Extended security service */ + /** + * Extended security service + */ private ExtendedSecurityService extendedSecurityService; - /** File plan service */ + /** + * File plan service + */ private FilePlanService filePlanService; - /** Records management notification helper */ + /** + * Records management notification helper + */ private RecordsManagementNotificationHelper notificationHelper; - /** Policy component */ + /** + * Policy component + */ private PolicyComponent policyComponent; - /** Ownable service */ + /** + * Ownable service + */ private OwnableService ownableService; - /** Capability service */ + /** + * Capability service + */ private CapabilityService capabilityService; - /** Rule service */ + /** + * Rule service + */ private RuleService ruleService; - /** File folder service */ + /** + * File folder service + */ private FileFolderService fileFolderService; - /** Record folder service */ + /** + * Record folder service + */ private RecordFolderService recordFolderService; - /** File plan role service */ + /** + * File plan role service + */ private FilePlanRoleService filePlanRoleService; - /** Permission service */ + /** + * Permission service + */ private PermissionService permissionService; - /** Version service */ + /** + * Version service + */ private VersionService versionService; - /** Relationship service */ + /** + * Relationship service + */ private RelationshipService relationshipService; - /** Disposition service */ + /** + * Disposition service + */ private DispositionService dispositionService; - /** records management container type */ + /** + * records management container type + */ private RecordsManagementContainerType recordsManagementContainerType; - /** recordable version service */ + /** + * recordable version service + */ private RecordableVersionService recordableVersionService; - /** list of available record meta-data aspects and the file plan types the are applicable to */ + /** + * list of available record meta-data aspects and the file plan types the are applicable to + */ private Map> recordMetaDataAspects; - /** policies */ + /** + * Freeze service + */ + private FreezeService freezeService; + + /** + * Namespace service + */ + private NamespaceService namespaceService; + + /** + * policies + */ private ClassPolicyDelegate beforeFileRecord; private ClassPolicyDelegate onFileRecord; private ClassPolicyDelegate beforeRecordDeclarationDelegate; @@ -292,7 +369,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param extendedSecurityService extended security service + * @param extendedSecurityService extended security service */ public void setExtendedSecurityService(ExtendedSecurityService extendedSecurityService) { @@ -300,7 +377,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param filePlanService file plan service + * @param filePlanService file plan service */ public void setFilePlanService(FilePlanService filePlanService) { @@ -316,7 +393,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param policyComponent policy component + * @param policyComponent policy component */ public void setPolicyComponent(PolicyComponent policyComponent) { @@ -324,7 +401,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param ownableService ownable service + * @param ownableService ownable service */ public void setOwnableService(OwnableService ownableService) { @@ -340,7 +417,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param ruleService rule service + * @param ruleService rule service */ public void setRuleService(RuleService ruleService) { @@ -388,7 +465,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param relationshipService relationship service + * @param relationshipService relationship service */ public void setRelationshipService(RelationshipService relationshipService) { @@ -396,7 +473,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param dispositionService disposition service + * @param dispositionService disposition service */ public void setDispositionService(DispositionService dispositionService) { @@ -404,7 +481,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param recordsManagementContainerType records management container type + * @param recordsManagementContainerType records management container type */ public void setRecordsManagementContainerType(RecordsManagementContainerType recordsManagementContainerType) { @@ -412,7 +489,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @param recordableVersionService recordable version service + * @param recordableVersionService recordable version service */ public void setRecordableVersionService(RecordableVersionService recordableVersionService) { @@ -424,6 +501,30 @@ public class RecordServiceImpl extends BaseBehaviourBean this.incompleteNodeTagger = incompleteNodeTagger; } + /** + * @param freezeService freeze service + */ + public void setFreezeService(FreezeService freezeService) + { + this.freezeService = freezeService; + } + + /** + * @param namespaceService namespace service + */ + public void setNamespaceService(NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + + /** + * @param checkMandatoryPropertiesEnabled true if check mandatory properties is enabled, false otherwise + */ + public void setCheckMandatoryPropertiesEnabled(boolean checkMandatoryPropertiesEnabled) + { + this.checkMandatoryPropertiesEnabled = checkMandatoryPropertiesEnabled; + } + /** * Init method */ @@ -443,11 +544,11 @@ public class RecordServiceImpl extends BaseBehaviourBean */ @Override @Behaviour - ( - kind = BehaviourKind.CLASS, - type = "rma:record", - notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT - ) + ( + kind = BehaviourKind.CLASS, + type = "rma:record", + notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT + ) public void onAddAspect(NodeRef nodeRef, QName aspect) { authenticationUtil.runAsSystem(new RunAsWork() @@ -470,10 +571,10 @@ public class RecordServiceImpl extends BaseBehaviourBean */ @Override @Behaviour - ( - kind = BehaviourKind.CLASS, - type = "sys:noContent" - ) + ( + kind = BehaviourKind.CLASS, + type = "sys:noContent" + ) public void onRemoveAspect(NodeRef nodeRef, QName aspect) { if (nodeService.hasAspect(nodeRef, ASPECT_RECORD)) @@ -494,11 +595,11 @@ public class RecordServiceImpl extends BaseBehaviourBean */ @Override @Behaviour - ( - kind = ASSOCIATION, - type = "rma:recordFolder", - notificationFrequency = FIRST_EVENT - ) + ( + kind = ASSOCIATION, + type = "rma:recordFolder", + notificationFrequency = FIRST_EVENT + ) public void onCreateChildAssociation(final ChildAssociationRef childAssocRef, final boolean bNew) { AuthenticationUtil.runAs(new RunAsWork() @@ -509,10 +610,10 @@ public class RecordServiceImpl extends BaseBehaviourBean try { NodeRef nodeRef = childAssocRef.getChildRef(); - if (nodeService.exists(nodeRef) && - !nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY) && - !nodeService.getType(nodeRef).equals(TYPE_RECORD_FOLDER) && - !nodeService.getType(nodeRef).equals(TYPE_RECORD_CATEGORY)) + if (nodeService.exists(nodeRef) && + !nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPORARY) && + !nodeService.getType(nodeRef).equals(TYPE_RECORD_FOLDER) && + !nodeService.getType(nodeRef).equals(TYPE_RECORD_CATEGORY)) { // store information about the 'new' record in the transaction // @since 2.3 @@ -521,8 +622,7 @@ public class RecordServiceImpl extends BaseBehaviourBean { Set newRecords = transactionalResourceHelper.getSet(KEY_NEW_RECORDS); newRecords.add(nodeRef); - } - else + } else { // if we are linking a record NodeRef parentNodeRef = childAssocRef.getParentRef(); @@ -538,13 +638,11 @@ public class RecordServiceImpl extends BaseBehaviourBean // recalculate disposition schedule for the record when linking it dispositionService.recalculateNextDispositionStep(nodeRef); } - } - catch (RecordLinkRuntimeException e) + } catch (RecordLinkRuntimeException e) { // rethrow exception throw e; - } - catch (AlfrescoRuntimeException e) + } catch (AlfrescoRuntimeException e) { // do nothing but log error LOGGER.warn("Unable to file pending record.", e); @@ -597,18 +695,18 @@ public class RecordServiceImpl extends BaseBehaviourBean */ @Override @Behaviour - ( - name = "onUpdateProperties", - kind = BehaviourKind.CLASS, - type= "rma:record" - ) + ( + name = "onUpdateProperties", + kind = BehaviourKind.CLASS, + type = "rma:record" + ) public void onUpdateProperties(final NodeRef nodeRef, final Map before, final Map after) { if (AuthenticationUtil.getFullyAuthenticatedUser() != null && - !AuthenticationUtil.isRunAsUserTheSystemUser() && - nodeService.exists(nodeRef) && - isRecord(nodeRef) && - !transactionalResourceHelper.getSet(KEY_IGNORE_ON_UPDATE).contains(nodeRef)) + !AuthenticationUtil.isRunAsUserTheSystemUser() && + nodeService.exists(nodeRef) && + isRecord(nodeRef) && + !transactionalResourceHelper.getSet(KEY_IGNORE_ON_UPDATE).contains(nodeRef)) { for (Map.Entry entry : after.entrySet()) { @@ -626,34 +724,32 @@ public class RecordServiceImpl extends BaseBehaviourBean // deal with date values, remove the seconds and milliseconds for the // comparison as they are removed from the submitted for data Calendar beforeCal = Calendar.getInstance(); - beforeCal.setTime((Date)beforeValue); + beforeCal.setTime((Date) beforeValue); Calendar afterCal = Calendar.getInstance(); - afterCal.setTime((Date)afterValue); + afterCal.setTime((Date) afterValue); beforeCal.set(Calendar.SECOND, 0); beforeCal.set(Calendar.MILLISECOND, 0); afterCal.set(Calendar.SECOND, 0); afterCal.set(Calendar.MILLISECOND, 0); propertyUnchanged = (beforeCal.compareTo(afterCal) == 0); - } - else if ((afterValue instanceof Boolean) && (beforeValue == null) && (afterValue.equals(Boolean.FALSE))) + } else if ((afterValue instanceof Boolean) && (beforeValue == null) && (afterValue.equals(Boolean.FALSE))) { propertyUnchanged = true; - } - else + } else { // otherwise propertyUnchanged = EqualsHelper.nullSafeEquals(beforeValue, afterValue); } if (!propertyUnchanged && - !(ContentModel.PROP_CONTENT.equals(property) && beforeValue == null) && - !isPropertyEditable(nodeRef, property)) + !(ContentModel.PROP_CONTENT.equals(property) && beforeValue == null) && + !isPropertyEditable(nodeRef, property)) { // the user can't edit the record property throw new ModelAccessDeniedException( "The user " + AuthenticationUtil.getFullyAuthenticatedUser() + - " does not have the permission to edit the record property " + property.toString() + - " on the node " + nodeRef.toString()); + " does not have the permission to edit the record property " + property.toString() + + " on the node " + nodeRef.toString()); } } } @@ -662,8 +758,7 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * Get map containing record metadata aspects. * - * @return {@link Map}<{@link QName}, {@link Set}<{@link QName}>> map containing record metadata aspects - * + * @return {@link Map}<{@link QName}, {@link Set}<{@link QName}>> map containing record metadata aspects * @since 2.2 */ protected Map> getRecordMetadataAspectsMap() @@ -721,8 +816,7 @@ public class RecordServiceImpl extends BaseBehaviourBean { // get the current set of file plan types for this aspect filePlanTypes = getRecordMetadataAspectsMap().get(recordMetadataAspect); - } - else + } else { // create a new set for the file plan type filePlanTypes = new HashSet(1); @@ -744,7 +838,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isRecordMetadataAspect(org.alfresco.service.namespace.QName) + * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isRecordMetadataAspect(org.alfresco.service.namespace.QName) */ @Override public boolean isRecordMetadataAspect(QName aspect) @@ -764,7 +858,7 @@ public class RecordServiceImpl extends BaseBehaviourBean { ClassDefinition classDefinition = propertyDefinition.getContainerClass(); if (classDefinition != null && - getRecordMetadataAspectsMap().containsKey(classDefinition.getName())) + getRecordMetadataAspectsMap().containsKey(classDefinition.getName())) { result = true; } @@ -867,8 +961,7 @@ public class RecordServiceImpl extends BaseBehaviourBean { // move the document into the file plan nodeService.moveNode(nodeRef, newRecordContainer, ContentModel.ASSOC_CONTAINS, parentAssoc.getQName()); - } - finally + } finally { behaviourFilter.enableBehaviour(); } @@ -907,14 +1000,12 @@ public class RecordServiceImpl extends BaseBehaviourBean // set the extended security extendedSecurityService.set(nodeRef, readersAndWriters); - } - finally + } finally { ruleService.enableRules(); } } - } - finally + } finally { ruleService.enableRuleType("outbound"); } @@ -955,8 +1046,7 @@ public class RecordServiceImpl extends BaseBehaviourBean LOGGER.debug(msg); throw new RecordCreationException(msg); } - } - else + } else { // verify that the provided file plan is actually a file plan if (!filePlanService.isFilePlan(filePlan)) @@ -1072,8 +1162,7 @@ public class RecordServiceImpl extends BaseBehaviourBean // create a copy of the original state and add it to the unfiled record container FileInfo recordInfo = fileFolderService.copy(nodeRef, unfiledRecordFolder, null); record = recordInfo.getNodeRef(); - } - finally + } finally { recordsManagementContainerType.enable(); } @@ -1084,8 +1173,7 @@ public class RecordServiceImpl extends BaseBehaviourBean try { nodeService.removeAspect(record, ContentModel.ASPECT_VERSIONABLE); - } - finally + } finally { behaviourFilter.enableBehaviour(ContentModel.ASPECT_VERSIONABLE); } @@ -1108,16 +1196,14 @@ public class RecordServiceImpl extends BaseBehaviourBean if (originalAssocs == null) { nodeService.removeAspect(record, ContentModel.ASPECT_COPIEDFROM); - } - else + } else { for (AssociationRef originalAssoc : originalAssocs) { nodeService.createAssociation(record, originalAssoc.getTargetRef(), ContentModel.ASSOC_ORIGINAL); } } - } - catch (FileNotFoundException e) + } catch (FileNotFoundException e) { throw new AlfrescoRuntimeException("Can't create recorded version, because copy fails.", e); } @@ -1133,7 +1219,7 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * Helper to get the latest version record for a given document (ie non-record) * - * @param nodeRef node reference + * @param nodeRef node reference * @return NodeRef latest version record, null otherwise */ private NodeRef getLatestVersionRecord(NodeRef nodeRef) @@ -1188,8 +1274,7 @@ public class RecordServiceImpl extends BaseBehaviourBean if (type == null) { type = ContentModel.TYPE_CONTENT; - } - else if (!dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) + } else if (!dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) { throw new AlfrescoRuntimeException("Record can only be created from a sub-type of cm:content."); } @@ -1234,8 +1319,7 @@ public class RecordServiceImpl extends BaseBehaviourBean } }); - } - finally + } finally { enablePropertyEditableCheck(); } @@ -1260,7 +1344,7 @@ public class RecordServiceImpl extends BaseBehaviourBean authenticationUtil.runAsSystem(new RunAsWork() { @Override - public Void doWork() throws Exception + public Void doWork() throws Exception { nodeService.addAspect(document, RecordsManagementModel.ASPECT_RECORD, null); @@ -1273,8 +1357,7 @@ public class RecordServiceImpl extends BaseBehaviourBean return null; } }); - } - finally + } finally { ruleService.enableRules(); enablePropertyEditableCheck(); @@ -1308,9 +1391,9 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * Helper method to 'file' a new document that arrived in the file plan structure. - * - * TODO atm we only 'file' content as a record .. may need to consider other types if we - * are to support the notion of composite records. + *

+ * TODO atm we only 'file' content as a record .. may need to consider other types if we + * are to support the notion of composite records. * * @param record node reference to record (or soon to be record!) */ @@ -1322,8 +1405,8 @@ public class RecordServiceImpl extends BaseBehaviourBean // we only support filling of content items // TODO composite record support needs to file containers too QName type = nodeService.getType(record); - if (ContentModel.TYPE_CONTENT.equals(type) || - dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) + if (ContentModel.TYPE_CONTENT.equals(type) || + dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT)) { // fire before file record policy beforeFileRecord.get(getTypeAndApsects(record)).beforeFileRecord(record); @@ -1347,94 +1430,6 @@ public class RecordServiceImpl extends BaseBehaviourBean } } - /** - * Helper method to 'complete' a record. - * - * @param record node reference to record - */ - public void complete(NodeRef record) - { - ParameterCheck.mandatory("item", record); - - // TODO get this from config - boolean checkMandatoryPropertiesEnabled = true; - - if (!checkMandatoryPropertiesEnabled || (isMandatoryPropertiesPopulated(record))) - { - disablePropertyEditableCheck(); - // Add the declared aspect - Map declaredProps = new HashMap<>(2); - declaredProps.put(RecordsManagementModel.PROP_DECLARED_AT, new Date()); - declaredProps.put(RecordsManagementModel.PROP_DECLARED_BY, AuthenticationUtil.getRunAsUser()); - nodeService.addAspect(record, RecordsManagementModel.ASPECT_DECLARED_RECORD, declaredProps); - enablePropertyEditableCheck(); - } - } - - /** - * Helper method to determine whether a record's mandatory properties are set. - * - * @param nodeRef node reference to record - * @return boolean true if all mandatory metadata properties are set, false otherwise - */ - public boolean isMandatoryPropertiesPopulated(NodeRef nodeRef) - { - boolean result = true; - - // check for missing mandatory metadata from type definitions - Map nodeRefProps = nodeService.getProperties(nodeRef); - QName nodeRefType = nodeService.getType(nodeRef); - - TypeDefinition typeDef = dictionaryService.getType(nodeRefType); - for (PropertyDefinition propDef : typeDef.getProperties().values()) - { - if (propDef.isMandatory() && nodeRefProps.get(propDef.getName()) == null) - { - result = false; - break; - } - } - - // check for missing mandatory metadata from aspect definitions - if (result) - { - // TODO change to aspects = getAspects(nodeRef) ? - Set aspects = nodeService.getAspects(nodeRef); - for (QName aspect : aspects) - { - AspectDefinition aspectDef = dictionaryService.getAspect(aspect); - for (PropertyDefinition propDef : aspectDef.getProperties().values()) - { - if (propDef.isMandatory() && nodeRefProps.get(propDef.getName()) == null) - { - result = false; - break; - } - } - } - } - - // check for missing mandatory metadata from custom aspect definitions - if (result) - { - Collection aspects = dictionaryService.getAspects(RM_CUSTOM_MODEL); - for (QName aspect : aspects) - { - AspectDefinition aspectDef = dictionaryService.getAspect(aspect); - for (PropertyDefinition propDef : aspectDef.getProperties().values()) - { - if (propDef.isMandatory() && nodeRefProps.get(propDef.getName()) == null) - { - result = false; - break; - } - } - } - } - - return result; - } - /** * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#rejectRecord(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) */ @@ -1469,10 +1464,10 @@ public class RecordServiceImpl extends BaseBehaviourBean // get record property values final Map properties = nodeService.getProperties(nodeRef); - final String recordId = (String)properties.get(PROP_IDENTIFIER); - final String documentOwner = (String)properties.get(PROP_RECORD_ORIGINATING_USER_ID); - final String originalName = (String)properties.get(PROP_ORIGIONAL_NAME); - final NodeRef originatingLocation = (NodeRef)properties.get(PROP_RECORD_ORIGINATING_LOCATION); + final String recordId = (String) properties.get(PROP_IDENTIFIER); + final String documentOwner = (String) properties.get(PROP_RECORD_ORIGINATING_USER_ID); + final String originalName = (String) properties.get(PROP_ORIGIONAL_NAME); + final NodeRef originatingLocation = (NodeRef) properties.get(PROP_RECORD_ORIGINATING_LOCATION); // we can only reject if the originating location is present if (originatingLocation != null) @@ -1501,7 +1496,7 @@ public class RecordServiceImpl extends BaseBehaviourBean { fileFolderService.rename(nodeRef, originalName); - String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); + String name = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); LOGGER.debug("Rename {} to {}", name, originalName); } @@ -1528,8 +1523,7 @@ public class RecordServiceImpl extends BaseBehaviourBean // send an email to the record creator notificationHelper.recordRejectedEmailNotification(nodeRef, recordId, documentOwner); } - } - finally + } finally { ruleService.enableRules(); } @@ -1546,7 +1540,7 @@ public class RecordServiceImpl extends BaseBehaviourBean for (QName aspect : aspects) { if (RM_URI.equals(aspect.getNamespaceURI()) || - RecordableVersionModel.RMV_URI.equals(aspect.getNamespaceURI())) + RecordableVersionModel.RMV_URI.equals(aspect.getNamespaceURI())) { nodeService.removeAspect(nodeRef, aspect); } @@ -1557,7 +1551,7 @@ public class RecordServiceImpl extends BaseBehaviourBean // Do not attempt to clean up rendition nodes which are not children of their source node. final boolean renditionRequiresCleaning = nodeService.exists(renditionNode) && - renditionAssoc.isPrimary(); + renditionAssoc.isPrimary(); if (renditionRequiresCleaning) { @@ -1613,7 +1607,7 @@ public class RecordServiceImpl extends BaseBehaviourBean for (AccessPermission perm : perms) { if ((perm.getPermission().contains(RMPermissionModel.EDIT_NON_RECORD_METADATA) || - perm.getPermission().contains(RMPermissionModel.EDIT_RECORD_METADATA))) + perm.getPermission().contains(RMPermissionModel.EDIT_RECORD_METADATA))) { LOGGER.debug(" ... " + perm.getAuthority() + " - " + perm.getPermission() + " - " + perm.getAccessStatus().toString()); } @@ -1630,8 +1624,7 @@ public class RecordServiceImpl extends BaseBehaviourBean if (result) { LOGGER.debug(" ... property marked as always editable."); - } - else + } else { boolean allowRecordEdit = false; boolean allowNonRecordEdit = false; @@ -1646,8 +1639,8 @@ public class RecordServiceImpl extends BaseBehaviourBean allowNonRecordEdit = true; } - if (AccessStatus.ALLOWED.equals(accessRecord) || - AccessStatus.ALLOWED.equals(accessDeclaredRecord)) + if (AccessStatus.ALLOWED.equals(accessRecord) || + AccessStatus.ALLOWED.equals(accessDeclaredRecord)) { LOGGER.debug(" ... user has edit record or declared metadata capability"); allowRecordEdit = true; @@ -1657,29 +1650,25 @@ public class RecordServiceImpl extends BaseBehaviourBean { LOGGER.debug(" ... so all properties can be edited."); result = true; - } - else if (allowNonRecordEdit && !allowRecordEdit) + } else if (allowNonRecordEdit && !allowRecordEdit) { // can only edit non record properties if (!isRecordMetadata(filePlan, property)) { LOGGER.debug(" ... property is not considered record metadata so editable."); result = true; - } - else + } else { LOGGER.debug(" ... property is considered record metadata so not editable."); } - } - else if (!allowNonRecordEdit && allowRecordEdit) + } else if (!allowNonRecordEdit && allowRecordEdit) { // can only edit record properties if (isRecordMetadata(filePlan, property)) { LOGGER.debug(" ... property is considered record metadata so editable."); result = true; - } - else + } else { LOGGER.debug(" ... property is not considered record metadata so not editable."); } @@ -1692,7 +1681,7 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * Helper method that indicates whether a property is considered record metadata or not. * - * @param property property + * @param property property * @return boolea true if record metadata, false otherwise */ private boolean isRecordMetadata(NodeRef filePlan, QName property) @@ -1712,8 +1701,7 @@ public class RecordServiceImpl extends BaseBehaviourBean if (parent != null && TYPE_NON_ELECTRONIC_DOCUMENT.equals(parent.getName())) { result = false; - } - else + } else { // check the URI's result = RECORD_MODEL_URIS.contains(property.getNamespaceURI()); @@ -1748,7 +1736,7 @@ public class RecordServiceImpl extends BaseBehaviourBean * Helper method to determine whether a property is protected at a dictionary definition * level. * - * @param property property qualified name + * @param property property qualified name * @return booelan true if protected, false otherwise */ private boolean isProtectedProperty(QName property) @@ -1808,8 +1796,7 @@ public class RecordServiceImpl extends BaseBehaviourBean if (!nodeService.hasAspect(nodeRef, typeQName)) { nodeService.addAspect(nodeRef, typeQName, null); - } - else + } else { LOGGER.info(I18NUtil.getMessage(MSG_NODE_HAS_ASPECT, nodeRef.toString(), typeQName.toString())); } @@ -1825,7 +1812,7 @@ public class RecordServiceImpl extends BaseBehaviourBean ParameterCheck.mandatory("recordFolder", recordFolder); // ensure we are linking a record to a record folder - if(isRecord(record) && isRecordFolder(recordFolder)) + if (isRecord(record) && isRecordFolder(recordFolder)) { // ensure that we are not linking a record to an existing location List parents = nodeService.getParentAssocs(record); @@ -1846,15 +1833,14 @@ public class RecordServiceImpl extends BaseBehaviourBean // create a secondary link to the record folder nodeService.addChild( - recordFolder, - record, - ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name)); + recordFolder, + record, + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name)); // recalculate disposition schedule for the record when linking it dispositionService.recalculateNextDispositionStep(record); - } - else + } else { // can only link a record to a record folder throw new RecordLinkRuntimeException("Can only link a record to a record folder."); @@ -1862,7 +1848,6 @@ public class RecordServiceImpl extends BaseBehaviourBean } /** - * * @param record * @param recordFolder */ @@ -1882,7 +1867,7 @@ public class RecordServiceImpl extends BaseBehaviourBean { // we can't link a record to an incompatible disposition schedule throw new RecordLinkRuntimeException("Cannot link a record to a record folder with an incompatible retention schedule. " - + "They must either both be record level or record folder level retentions."); + + "They must either both be record level or record folder level retentions."); } } } @@ -1898,7 +1883,7 @@ public class RecordServiceImpl extends BaseBehaviourBean ParameterCheck.mandatory("recordFolder", recordFolder); // ensure we are unlinking a record from a record folder - if(isRecord(record) && isRecordFolder(recordFolder)) + if (isRecord(record) && isRecordFolder(recordFolder)) { // check that we are not trying to unlink the primary parent NodeRef primaryParent = nodeService.getPrimaryParent(record).getParentRef(); @@ -1912,8 +1897,7 @@ public class RecordServiceImpl extends BaseBehaviourBean // recalculate disposition schedule for record after unlinking it dispositionService.recalculateNextDispositionStep(record); - } - else + } else { // can only unlink a record from a record folder throw new RecordLinkRuntimeException("Can only unlink a record from a record folder."); @@ -1925,11 +1909,11 @@ public class RecordServiceImpl extends BaseBehaviourBean */ @Override @Behaviour - ( - kind = BehaviourKind.CLASS, - type = "rma:record", - notificationFrequency = TRANSACTION_COMMIT - ) + ( + kind = BehaviourKind.CLASS, + type = "rma:record", + notificationFrequency = TRANSACTION_COMMIT + ) public void onContentUpdate(NodeRef nodeRef, boolean newContent) { if (nodeService.exists(nodeRef) && !nodeService.hasAspect(nodeRef, ContentModel.ASPECT_HIDDEN) && !nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE)) @@ -1942,7 +1926,7 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * Invoke invokeBeforeRecordDeclaration policy * - * @param nodeRef node reference + * @param nodeRef node reference */ protected void invokeBeforeRecordDeclaration(NodeRef nodeRef) { @@ -1956,7 +1940,7 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * Invoke invokeOnRecordDeclaration policy * - * @param nodeRef node reference + * @param nodeRef node reference */ protected void invokeOnRecordDeclaration(NodeRef nodeRef) { @@ -1970,7 +1954,7 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * Invoke invokeBeforeRecordRejection policy * - * @param nodeRef node reference + * @param nodeRef node reference */ protected void invokeBeforeRecordRejection(NodeRef nodeRef) { @@ -1984,7 +1968,7 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * Invoke invokeOnRecordRejection policy * - * @param nodeRef node reference + * @param nodeRef node reference */ protected void invokeOnRecordRejection(NodeRef nodeRef) { @@ -1997,19 +1981,185 @@ public class RecordServiceImpl extends BaseBehaviourBean /** * RM-5244 - workaround to make sure the incomplete aspect is removed - * + * * @param nodeRef the node to reevaluate for */ private void reevaluateIncompleteTag(NodeRef nodeRef) { /* * Check if the node has the aspect because the reevaluation is expensive. - * If the node doesn't have the aspect it means IncompleteNodeTagger didn't load before TransactionBehaviourQueue + * If the node doesn't have the aspect it means IncompleteNodeTagger didn't load before TransactionBehaviourQueue * and we don't need to reevaluate. */ - if(nodeService.hasAspect(nodeRef, ContentModel.ASPECT_INCOMPLETE)) + if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_INCOMPLETE)) { incompleteNodeTagger.beforeCommit(false); } } + + /** + * Completes a record + * + * @param nodeRef Record node reference + */ + @Override + public void complete(NodeRef nodeRef) + { + if (nodeService.exists(nodeRef) && isRecord(nodeRef) && !freezeService.isFrozen(nodeRef)) + { + if (!isDeclared(nodeRef)) + { + // if the record is newly created make sure the record identifier is set before completing the record + Set newRecords = transactionalResourceHelper.getSet(RecordServiceImpl.KEY_NEW_RECORDS); + if (newRecords.contains(nodeRef)) + { + generateRecordIdentifier(nodeService, identifierService, nodeRef); + } + + List missingProperties = new ArrayList<>(5); + // Aspect not already defined - check mandatory properties then add + if (!checkMandatoryPropertiesEnabled || mandatoryPropertiesSet(nodeRef, missingProperties)) + { + disablePropertyEditableCheck(); + try + { + // Add the declared aspect + Map declaredProps = new HashMap<>(2); + declaredProps.put(PROP_DECLARED_AT, new Date()); + declaredProps.put(PROP_DECLARED_BY, AuthenticationUtil.getRunAsUser()); + nodeService.addAspect(nodeRef, ASPECT_DECLARED_RECORD, declaredProps); + + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() + { + // remove all owner related rights + ownableService.setOwner(nodeRef, OwnableService.NO_OWNER); + return null; + } + }); + } finally + { + enablePropertyEditableCheck(); + } + } else + { + LOGGER.debug(buildMissingPropertiesErrorString(missingProperties)); + throw new IntegrityException("The record has missing mandatory properties.", null); + } + } else + { + throw new IntegrityException("The record is already completed.", null); + } + } else + { + if (LOGGER.isWarnEnabled()) + { + LOGGER.warn(I18NUtil.getMessage(MSG_UNDECLARED_ONLY_RECORDS, nodeRef.toString())); + } + throw new IntegrityException("The record does not exist or is frozen.", null); + } + } + + private String buildMissingPropertiesErrorString(List missingProperties) + { + StringBuilder builder = new StringBuilder(255); + builder.append(I18NUtil.getMessage(MSG_NO_DECLARE_MAND_PROP)); + builder.append(" "); + for (String missingProperty : missingProperties) + { + builder.append(missingProperty).append(", "); + } + return builder.toString(); + } + + /** + * Helper method to check whether all the mandatory properties of the node have been set + * + * @param nodeRef node reference + * @return boolean true if all mandatory properties are set, false otherwise + */ + private boolean mandatoryPropertiesSet(final NodeRef nodeRef, final List missingProperties) + { + Map nodeRefProps = nodeService.getProperties(nodeRef); + QName nodeRefType = nodeService.getType(nodeRef); + + // check for missing mandatory metadata from type definitions + TypeDefinition typeDef = dictionaryService.getType(nodeRefType); + checkDefinitionMandatoryPropsSet(typeDef, nodeRefProps, missingProperties); + + // check for missing mandatory metadata from aspect definitions + Set aspects = nodeService.getAspects(nodeRef); + for (QName aspect : aspects) + { + AspectDefinition aspectDef = dictionaryService.getAspect(aspect); + checkDefinitionMandatoryPropsSet(aspectDef, nodeRefProps, missingProperties); + } + + // check for missing mandatory metadata from custom aspect definitions + QName customAspect = getCustomAspectImpl(nodeRefType); + AspectDefinition aspectDef = dictionaryService.getAspect(customAspect); + checkDefinitionMandatoryPropsSet(aspectDef, nodeRefProps, missingProperties); + + return missingProperties.isEmpty(); + } + + /** + * Helper method to check whether all the definition mandatory properties of the node have been set + * + * @param classDef the ClassDefinition defining the properties to be checked + * @param nodeRefProps the properties of the node to be checked + * @param missingProperties the list of mandatory properties found to be missing (currently only the first one) + * @return boolean true if all mandatory properties are set, false otherwise + */ + private void checkDefinitionMandatoryPropsSet(final ClassDefinition classDef, final Map nodeRefProps, + final List missingProperties) + { + for (PropertyDefinition propDef : classDef.getProperties().values()) + { + if (propDef.isMandatory() && nodeRefProps.get(propDef.getName()) == null) + { + logMissingProperty(propDef, missingProperties); + ; + } + } + } + + /** + * Log information about missing properties. + * + * @param propDef property definition + * @param missingProperties missing properties + */ + private void logMissingProperty(PropertyDefinition propDef, List missingProperties) + { + if (LOGGER.isWarnEnabled()) + { + StringBuilder msg = new StringBuilder(); + msg.append("Mandatory property missing: ").append(propDef.getName()); + LOGGER.warn(msg.toString()); + } + missingProperties.add(propDef.getName().toString()); + } + + /** + * Helper method to get the custom aspect for a given nodeRef type + * + * @param nodeRefType the node type for which to return custom aspect QName + * @return QName custom aspect + */ + private QName getCustomAspectImpl(QName nodeRefType) + { + QName aspect = ASPECT_RECORD; + if (nodeRefType.equals(TYPE_NON_ELECTRONIC_DOCUMENT)) + { + aspect = TYPE_NON_ELECTRONIC_DOCUMENT; + } + + // get customAspectImpl + String localName = aspect.toPrefixString(namespaceService).replace(":", ""); + localName = MessageFormat.format("{0}CustomProperties", localName); + return QName.createQName(RM_CUSTOM_URI, localName); + } } diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CompleteRecordTest.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CompleteRecordTest.java index b73ecc6f78..7642f101bb 100644 --- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CompleteRecordTest.java +++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/CompleteRecordTest.java @@ -32,8 +32,8 @@ import java.util.HashMap; import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionResult; -import org.alfresco.module.org_alfresco_module_rm.action.impl.DeclareRecordAction; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementCustomModel; +import org.alfresco.module.org_alfresco_module_rm.record.RecordServiceImpl; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; @@ -55,9 +55,9 @@ public class CompleteRecordTest extends BaseRMTestCase private static final boolean OPTIONAL_METADATA = false; /** - * complete record action + * Record service impl */ - private DeclareRecordAction action; + private RecordServiceImpl recordServiceImpl; /** * @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase#initServices() @@ -67,8 +67,8 @@ public class CompleteRecordTest extends BaseRMTestCase { super.initServices(); - // get the action - action = (DeclareRecordAction) applicationContext.getBean("declareRecord"); + // get the record service + recordServiceImpl = (RecordServiceImpl) applicationContext.getBean("recordService"); } /** @@ -80,7 +80,7 @@ public class CompleteRecordTest extends BaseRMTestCase super.tearDownImpl(); // ensure action is returned to original state - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); } /** @@ -100,7 +100,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // create a record record = utils.createRecord(rmFolder, "record.txt", "title"); @@ -140,7 +140,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // create a record record = utils.createRecord(rmFolder, "record.txt", "title"); @@ -183,7 +183,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() throws Exception { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // create the custom metadata definition (that has a mandatory property) for electronic records defineCustomMetadata(CUSTOM_ELECTRONIC_TEST, ASPECT_RECORD, MANDATORY_METADATA); @@ -229,7 +229,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() throws Exception { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // define the custom metadata definition (that has a mandatory property) defineCustomMetadata(CUSTOM_ELECTRONIC_TEST, ASPECT_RECORD, MANDATORY_METADATA); @@ -279,7 +279,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() throws Exception { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // create the custom metadata definition (that has a mandatory property) for non-electronic records defineCustomMetadata(CUSTOM_NON_ELECTRONIC_TEST, TYPE_NON_ELECTRONIC_DOCUMENT, MANDATORY_METADATA); @@ -326,7 +326,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() throws Exception { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // create the custom metadata definition (that has a mandatory property) defineCustomMetadata(CUSTOM_NON_ELECTRONIC_TEST, TYPE_NON_ELECTRONIC_DOCUMENT, MANDATORY_METADATA); @@ -375,7 +375,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() throws Exception { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // create the custom metadata definition (that does not have a mandatory property) defineCustomMetadata(CUSTOM_ELECTRONIC_TEST, ASPECT_RECORD, OPTIONAL_METADATA); @@ -422,7 +422,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() throws Exception { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // create the record custom metadata definition (that has a mandatory property) defineCustomMetadata(CUSTOM_ELECTRONIC_TEST, ASPECT_RECORD, MANDATORY_METADATA); @@ -469,7 +469,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() throws Exception { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(true); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(true); // create the non-electronic record custom metadata definition (that has a mandatory property) defineCustomMetadata(CUSTOM_NON_ELECTRONIC_TEST, TYPE_NON_ELECTRONIC_DOCUMENT, MANDATORY_METADATA); @@ -515,7 +515,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() { // disable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(false); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(false); // create a record record = utils.createRecord(rmFolder, "record.txt", "title"); @@ -555,7 +555,7 @@ public class CompleteRecordTest extends BaseRMTestCase public void given() { // enable mandatory parameter check - action.setCheckMandatoryPropertiesEnabled(false); + recordServiceImpl.setCheckMandatoryPropertiesEnabled(false); // create a record record = utils.createRecord(rmFolder, "record.txt", "title");