diff --git a/mmt/alfresco-mmt-main.jar b/mmt/alfresco-mmt-main.jar
index d395dfa05d..3e7b5abe47 100644
Binary files a/mmt/alfresco-mmt-main.jar and b/mmt/alfresco-mmt-main.jar differ
diff --git a/mmt/commons-compress-1.4.jar b/mmt/commons-compress-1.4.jar
new file mode 100644
index 0000000000..6569361243
Binary files /dev/null and b/mmt/commons-compress-1.4.jar differ
diff --git a/mmt/truezip-driver-file-7.5.5.jar b/mmt/truezip-driver-file-7.5.5.jar
new file mode 100644
index 0000000000..fa48008173
Binary files /dev/null and b/mmt/truezip-driver-file-7.5.5.jar differ
diff --git a/mmt/truezip-driver-zip-7.5.5.jar b/mmt/truezip-driver-zip-7.5.5.jar
new file mode 100644
index 0000000000..cc7e3e3ab5
Binary files /dev/null and b/mmt/truezip-driver-zip-7.5.5.jar differ
diff --git a/mmt/truezip-file-7.5.5.jar b/mmt/truezip-file-7.5.5.jar
new file mode 100644
index 0000000000..2b01e1bcc5
Binary files /dev/null and b/mmt/truezip-file-7.5.5.jar differ
diff --git a/mmt/truezip-kernel-7.5.5.jar b/mmt/truezip-kernel-7.5.5.jar
new file mode 100644
index 0000000000..3fb3cbfa7c
Binary files /dev/null and b/mmt/truezip-kernel-7.5.5.jar differ
diff --git a/mmt/truezip-swing-7.5.5.jar b/mmt/truezip-swing-7.5.5.jar
new file mode 100644
index 0000000000..fbe0b1f391
Binary files /dev/null and b/mmt/truezip-swing-7.5.5.jar differ
diff --git a/mmt/xz-1.0.jar b/mmt/xz-1.0.jar
new file mode 100644
index 0000000000..a848f16dcd
Binary files /dev/null and b/mmt/xz-1.0.jar differ
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/bootstrap/content/rmEventConfigBootstrap.json b/rm-server/config/alfresco/module/org_alfresco_module_rm/bootstrap/content/rmEventConfigBootstrap.json
index 07cab10ffa..a19fbfeece 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/bootstrap/content/rmEventConfigBootstrap.json
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/bootstrap/content/rmEventConfigBootstrap.json
@@ -39,7 +39,7 @@
{
"eventType" : "rmEventType.crossReferencedRecordTransfered",
"eventName" : "related_record_trasfered_inactive_storage",
- "eventDisplayLabel" : "Related Record Transfered To Inactive Storage"
+ "eventDisplayLabel" : "Related Record Transferred To Inactive Storage"
},
{
"eventType" : "rmEventType.obsolete",
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
index 898b546ea9..497a7e661d 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/capability/rm-capabilities-fileplan-context.xml
@@ -29,7 +29,12 @@
FILE_PLAN
-
+
+
+
+
+
+
+
+
+
+
+ FILE_PLAN
+ RECORD_CATEGORY
+ RECORD_FOLDER
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/dod5015/dod5015-model_es.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/dod5015/dod5015-model_es.properties
new file mode 100644
index 0000000000..749439a7b6
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/dod5015/dod5015-model_es.properties
@@ -0,0 +1,73 @@
+dod_dod5015.description=Modelo de contenido DOD5015
+
+dod_dod5015.type.dod_recordSeries.title=Series de registros (obsoletas)
+dod_dod5015.type.dod_recordSeries.description=Series de registros (obsoletas)
+
+dod_dod5015.aspect.dod_scannedRecord.title=Registro escaneado
+dod_dod5015.aspect.dod_scannedRecord.description=Registro escaneado
+dod_dod5015.property.dod_scannedFormat.title=Formato de imagen
+dod_dod5015.property.dod_scannedFormat.description=Formato de imagen
+dod_dod5015.property.dod_scannedFormatVersion.title=Formato de imagen y versi\u00f3n
+dod_dod5015.property.dod_scannedFormatVersion.description=Formato de imagen y versi\u00f3n
+dod_dod5015.property.dod_resolutionX.title=Resoluci\u00f3n de imagen X
+dod_dod5015.property.dod_resolutionX.description=Resoluci\u00f3n de imagen x
+dod_dod5015.property.dod_resolutionY.title=Resoluci\u00f3n de imagen Y
+dod_dod5015.property.dod_resolutionY.description=Resoluci\u00f3n de imagen Y
+dod_dod5015.property.dod_scannedBitDepth.title=Profundidad de bit escaneada
+dod_dod5015.property.dod_scannedBitDepth.description=Profundidad de bit escaneada
+
+dod_dod5015.aspect.dod_pdfRecord.title=Registro PDF
+dod_dod5015.aspect.dod_pdfRecord.description=Registro PDF
+dod_dod5015.property.dod_producingApplication.title=Produciendo aplicaci\u00f3n
+dod_dod5015.property.dod_producingApplication.description=Produciendo aplicaci\u00f3n
+dod_dod5015.property.dod_producingApplicationVersion.title=Produciendo versi\u00f3n de aplicaci\u00f3n
+dod_dod5015.property.dod_producingApplicationVersion.description=Produciendo versi\u00f3n de aplicaci\u00f3n
+dod_dod5015.property.dod_pdfVersion.title=Versi\u00f3n en PDF
+dod_dod5015.property.dod_pdfVersion.description=Versi\u00f3n en PDF
+dod_dod5015.property.dod_creatingApplication.title=Creando aplicaci\u00f3n
+dod_dod5015.property.dod_creatingApplication.description=Creando aplicaci\u00f3n
+dod_dod5015.property.dod_documentSecuritySettings.title=Configuraci\u00f3n de seguridad del documento
+dod_dod5015.property.dod_documentSecuritySettings.description=Configuraci\u00f3n de seguridad del documento
+
+dod_dod5015.aspect.dod_digitalPhotographRecord.title=Registro fotogr\u00e1fico digital
+dod_dod5015.aspect.dod_digitalPhotographRecord.description=Registro fotogr\u00e1fico digital
+dod_dod5015.property.dod_caption.title=T\u00edtulo
+dod_dod5015.property.dod_caption.description=T\u00edtulo
+dod_dod5015.property.dod_photographer.title=Fot\u00f3grafo
+dod_dod5015.property.dod_photographer.description=Fot\u00f3grafo
+dod_dod5015.property.dod_copyright.title=Copyright
+dod_dod5015.property.dod_copyright.description=Copyright
+dod_dod5015.property.dod_bitDepth.title=Profundidad de color
+dod_dod5015.property.dod_bitDepth.description=Profundidad de color
+dod_dod5015.property.dod_imageSizeX.title=Tama\u00f1o de imagen X
+dod_dod5015.property.dod_imageSizeX.description=Tama\u00f1o de imagen X
+dod_dod5015.property.dod_imageSizeY.title=Tama\u00f1o de imagen Y
+dod_dod5015.property.dod_imageSizeY.description=Tama\u00f1o de imagen Y
+dod_dod5015.property.dod_imageSource.title=Procedencia de imagen
+dod_dod5015.property.dod_imageSource.description=Procedencia de imagen
+dod_dod5015.property.dod_compression.title=Compresi\u00f3n
+dod_dod5015.property.dod_compression.description=Compresi\u00f3n
+dod_dod5015.property.dod_iccIcmProfile.title=Perfil ICC/ICM
+dod_dod5015.property.dod_iccIcmProfile.description=Perfil ICC/ICM
+dod_dod5015.property.dod_exifInformation.title=Informaci\u00f3n EXIF
+dod_dod5015.property.dod_exifInformation.description=Informaci\u00f3n EXIF
+
+dod_dod5015.aspect.dod_webRecord.title=Registro web
+dod_dod5015.aspect.dod_webRecord.description=Registro web
+dod_dod5015.property.dod_webFileName.title=Nombre del archivo web
+dod_dod5015.property.dod_webFileName.description=Nombre del archivo web
+dod_dod5015.property.dod_webPlatform.title=Plataforma web
+dod_dod5015.property.dod_webPlatform.description=Plataforma web
+dod_dod5015.property.dod_webSiteName.title=Nombre del sitio web
+dod_dod5015.property.dod_webSiteName.description=Nombre del sitio web
+dod_dod5015.property.dod_webSiteURL.title=URL del sitio web
+dod_dod5015.property.dod_webSiteURL.description=URL del sitio web
+dod_dod5015.property.dod_captureMethod.title=M\u00e9todo de captura
+dod_dod5015.property.dod_captureMethod.description=M\u00e9todo de captura
+dod_dod5015.property.dod_captureDate.title=Fecha de captura
+dod_dod5015.property.dod_captureDate.description=Fecha de captura
+dod_dod5015.property.dod_contact.title=Contacto
+dod_dod5015.property.dod_contact.description=Contacto
+dod_dod5015.property.dod_contentManagementSystem.title=Sistema de gesti\u00f3n de contenidos
+dod_dod5015.property.dod_contentManagementSystem.description=Sistema de gesti\u00f3n de contenidos
+
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/action-service.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/action-service.properties
index c55856199e..0d8f4ea5ef 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/action-service.properties
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/action-service.properties
@@ -30,7 +30,7 @@ rm.action.no-read-mime-message=Unable to read mime message, because {0}.
rm.action.email-declared=Can not split email, because record has already been declared. (actionedUponNodeRef={0})
rm.action.email-not-record=Can no split email, because node is not a record. (actionedUponNodeRef={0})
rm.action.email-create-child-assoc=Unable to create custom child association.
-rm.action.node-already-transfer=Node is already being transfered.
+rm.action.node-already-transfer=Node is already being transffered.
rm.action.node-not-transfer=Node is not a transfer object.
rm.action.undo-not-last=Can not undo cut off, because last disposition action was not cut off.
rm.action.records_only_undeclared=Only records can be undeclared.
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/action-service_es.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/action-service_es.properties
new file mode 100644
index 0000000000..58a2bb006d
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/action-service_es.properties
@@ -0,0 +1,37 @@
+rm.action.not-defined=No se ha definido la acci\u00f3n de gesi\u00f3n de registros {0}.
+rm.action.no-implicit-noderef=No se pudo ejecutar la acci\u00f3n de gesti\u00f3n de registros porque la imprementaci\u00f3n de la acci\u00f3n {0} no proporciona un nodeRef impl\u00edcito.
+rm.action.record-not-declared=No se pudo ejecutar la acci\u00f3n de disposici\u00f3n {0} porque no se declar\u00f3 el registro. (actionedUponNodeRef={1})
+rm.action.expected-record-level=No se pudo ejecutar la acci\u00f3n de disposici\u00f3n {0} porque la disposici\u00f3n solamente se espera para registros y este nodo no es un registro. (actionedUponNodeRef={1})
+rm.action.not-all-records-declared=No se pudo ejecutar la acci\u00f3n de disposici\u00f3n {0} porque no se han declarado todos los registros. (actionedUponNodeRef={1})
+rm.action.not-eligible=No se pudo ejecutar la acci\u00f3n de disposici\u00f3n {0} porque la siguiente acci\u00f3n de disposici\u00f3n del registro o el fichero de registros no es v\u00e1lida. (actionedUponNodeRef={1})
+rm.action.no-disposition-instructions=No se encontrarion instrucciones de disposici\u00f3n para el nodo. No se ha podido ejecutar la acci\u00f3n de disposici\u00f3n {0} . (nodeRef={1})
+rm.action.no-disposition-lisfecycle-set=No se pudo ejecutar la acci\u00f3n de disposici\u00f3n {0} porque el nodo no tiene un ciclo de vida de disposici\u00f3n especificado. (nodeRef={1})
+rm.action.next-disp-not-set=No se pudo ejecutar la acci\u00f3n de disposici\u00f3n {0} porque no se ha especificado la siguiente acci\u00f3n de disposici\u00f3n. (nodeRef={1})
+rm.action.not-next-disp=No se pudo ejecutar la aci\u00f3n de disposici\u00f3n {0} porque no es la siguiente acci\u00f3n de disposici\u00f3n para este registro o fichero de registros. (nodeRef={1})
+rm.action.not-record-folder=No se pudo ejecutar la acci\u00f3n de disposici\u00f3n {0} porque la disposici\u00f3n solamente se espera para ficheros de registros y este nodo no es un fichero de registros. (nodeRef={1})
+rm.action.actioned-upon-not-record=No se pudo ejecutar/ no es posible/no se puede ejecutar la acci\u00f3n {0} porque el nodo sobre el que se ejecuta no es un registro. (filePlanComponet={1})
+rm.action.custom-aspect-not-recognised=No se puede aplicar el tipo personalizado porque no se reconoce. (customAspect={0})
+rm.action.close-record-folder-not-folder=No se pudo cerrar el fichero de registros porque el nodo no es un fichero de registros. (nodeRef={0})
+rm.action.event-no-disp-lc=No se ha podido completar el evento {0} porque no se ha definido en el ciclo de vida de disposici\u00f3n.
+rm.action.undeclared-only-records=Solamente pueden dejarse sin declarar los registros. (nodeRef={0})
+rm.action.no-declare-mand-prop=No se puede declarar el registro porque no se han especificado todas las propiedades de registro obligatorias.
+rm.action.ghosted-prop-update=Las propiedades del contenido de un registro anulado anteriormente no se pueden actualizar.
+rm.action.valid-date-disp-asof=Debe especificarse una fecha v\u00e1lida cuando se especifica la acci\u00f3n de disposici\u00f3n a partir de dicha fecha.
+rm.action.disp-asof-lifecycle-applied=No es v\u00e1lido editar la disposici\u00f3n de fecha de un registro o fichero de registros al que se ha aplicado un ciclo de vida.
+rm.action.hold-edit-reason-none=No se puede editar el motivo de bloqueo porque no se ha proporcionado ninguno.
+rm.action.hold-edit-type=No se puede editar el motivo de bloqueo porque el nodo sobre el que se aplica una acci\u00f3n no es del tipo {0}. (nodeRef={1})
+rm.action.specify-avlid-date=Debe especificarse una fecha v\u00e1lida cuando se especifica la revisi\u00f3n a partir de dicha fecha.
+rm.action.review-details-only=Solamente se pueden editar los detalles de revisi\u00f3n de registros vitales.
+rm.action.freeze-no-reason=No se puede congelar un registro sin motivo.
+rm.action.freeze-only-records-folders=Solamente se pueden congelar registros o ficheros de registro.
+rm.action.no-open-record-folder=No se pudo abrir el fichero de registro porque el nodo no es un fichero de registro. (actionedUponNodeRef={0})
+rm.action.not-hold-type=No se puede retirar el bloqueo porque el nodo no es del tipo {0}. (actionedUponNodeRef={1})
+rm.action.no-read-mime-message=No se pudo leer el mensaje de MIME porque {0}.
+rm.action.email-declared=No se puede dividir el correo electr\u00f3nico porque ya se ha declarado el registro. (actionedUponNodeRef={0})
+rm.action.email-not-record=No se puede dividir el correo electr\u00f3nico porque el nodo no es un registro. (actionedUponNodeRef={0})
+rm.action.email-create-child-assoc=No se pudo crear una asociaci\u00f3n hija personalizada.
+rm.action.node-already-transfer=Ya se est\u00e1 transfiriendo el nodo.
+rm.action.node-not-transfer=El nodo no es un objeto de transferencia.
+rm.action.undo-not-last=No se puede deshacer la interrupci\u00f3n porque la \u00faltima acci\u00f3n de disposici\u00f3n no se interrumpi\u00f3.
+rm.action.records_only_undeclared=Solamente pueden desdeclararse registros.
+rm.action.event-not-undone=No se puede deshacer {0} porque no est\u00e1 definido en el ciclo de vida de la disposici\u00f3n.
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/admin-service_es.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/admin-service_es.properties
new file mode 100644
index 0000000000..4e44a6c311
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/admin-service_es.properties
@@ -0,0 +1,21 @@
+rm.admin.service-not-init=No se ha inicializado el servicio de personalizaci\u00f3n.
+rm.admin.not-customisable=La clase {0} no es personalizable.
+rm.admin.invalid-custom-aspect=No se pudo encontrar el aspecto personalizado {0} para la clase personalizable {1}.
+rm.admin.property-already-exists=La propiedad {0} ya existe.
+rm.admin.cannot-apply-constraint=No se puede aplicar la restricci\u00f3n {0} a la propiedad {1} con el tipo de datos {2}. (expected: dataType = TEXT)
+rm.admin.prop-exist=No se puede encontrar la propiedad personalizada {0}.
+rm.admin.custom-prop-exist=El modelo personalizado no contiene la propiedad {0}.
+rm.admin.unknown-aspect=Aspecto desconocido {0}.
+rm.admin.ref-exist= No se puede encontrar la referencia personalizada {0}.
+rm.admin.ref-label-in-use=La etiqueta de referencia {0} ya est\u00e1 en uso.
+rm.admin.assoc-exists=La asociaci\u00f3n {0} ya existe.
+rm.admin.child-assoc-exists=La asociaci\u00f3n hija {0} ya existe.
+rm.admin.cannot-find-assoc-def=No se puede encontrar la definici\u00f3n de asociaci\u00f3n {0}.
+rm.admin.constraint-exists=La restriccci\u00f3n {0} ya existe.
+rm.admin.contraint-cannot-find=No se puede encontrar la definici\u00f3n para la restricci\u00f3n {0}.
+rm.admin.unexpected_type_constraint=Tipo inesperado {0} para la restricci\u00f3n {1}, se espera {2}.
+rm.admin.custom-model-not-found=No se encuentra el modelo personalizado {0}.
+rm.admin.custom-model-no-content=El modelo personalizado no tiene contenido. (nodeRef={0})
+rm.admin.error-write-custom-model=Error al escribir el contenido del modelo personalizado. (nodeRef={0}).
+rm.admin.error-client-id=Error al generar Qname porque el Id del cliente ya est\u00e1 en uso. (clientid={0})
+rm.admin.error-split-id=No se pudo dividir la Id {1}, porque el separador {1} no est\u00e1 presente.
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/audit-service.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/audit-service.properties
index 6f6d53ded6..da7353c5f0 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/audit-service.properties
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/audit-service.properties
@@ -31,4 +31,6 @@ rm.audit.pdf-record=Set Record As PDF A Record
rm.audit.photo-record=Set Record As A Digital Photographic Record
rm.audit.web-record=Set Record As A Web Record
rm.audit.trail-file-fail=Failed to generate audit trail file.
-rm.audit.audit-report=Audit Report
\ No newline at end of file
+rm.audit.audit-report=Audit Report
+rm.audit.create-disposition-schedule=Create Disposition Schedule
+rm.audit.unfreeze=Unfreeze
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/audit-service_es.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/audit-service_es.properties
new file mode 100644
index 0000000000..aca146a151
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/audit-service_es.properties
@@ -0,0 +1,34 @@
+rm.audit.updated-metadata=Metadatos actualizados
+rm.audit.created-object=Objeto creado
+rm.audit.delte-object=Eliminar objeto
+rm.audit.login-succeeded=Sesi\u00f3n iniciada con \u00e9xito
+rm.audit.login-failed=Error al iniciar sesi\u00f3n
+rm.audit.filed-record=Registro archivado
+rm.audit.reviewed=Revisado
+rm.audit.cut-off=Interrumpido
+rm.audit.reversed-cut-off=Interrupci\u00f3n revertida
+rm.audit.destroyed-item=Objeto anulado
+rm.audit.opened-record-folder=Carpeta de registros abierta
+rm.audit.closed-record-folder=Carpeta de registros cerrada
+rm.audit.setup-recorder-folder=Carpeta de registros configurada
+rm.audit.declared-record=Registro declarado
+rm.audit.undeclared-record=Registro no declarado
+rm.audit.froze-item=Elemento fijado
+rm.audit.relinquised-hold=Bloqueo eliminado
+rm.audit.updated-hold-reason=Raz\u00f3n de bloqueo actualizada
+rm.audit.updated-review-as-of-date=Revisi\u00f3n a partir de la fecha actualizada
+rm.audit.updated-disposition-as-of-date=Disposici\u00f3n a partir de la fecha actualizada
+rm.audit.updated-vital-record-definition=Definici\u00f3n de registro vital actualizada
+rm.audit.updated-disposition-action-definition=Definici\u00f3n de acci\u00f3n de disposici\u00f3n actualizada
+rm.audit.completed-event=Evento completado
+rm.audit.revered-complete-event=Evento completado revertido
+rm.audit.transferred-item=Elemento transferido
+rm.audit.completed-transfer=Transferencia completada
+rm.audit.accession=Acceso
+rm.audit.copmleted-accession=Acceso completado
+rm.audit.scanned-record=Establecer registro como registro escaneado
+rm.audit.pdf-record=Establecer registro como registro PDF
+rm.audit.photo-record=Establecer registro como registro fotogr\u00e1fico digital
+rm.audit.web-record=Establecer registro como registro web
+rm.audit.trail-file-fail=Error al generar fichero de pista de auditor\u00eda.
+rm.audit.audit-report=Informe de auditor\u00eda
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/notification-service_es.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/notification-service_es.properties
new file mode 100644
index 0000000000..080a7f74fa
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/notification-service_es.properties
@@ -0,0 +1,2 @@
+notification.dueforreview.subject=Registros pendientes de notificaci\u00f3n de revisi\u00f3n
+notification.superseded.subject=Notificaci\u00f3n de registro reemplazada
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/records-management-service_es.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/records-management-service_es.properties
new file mode 100644
index 0000000000..35f266300d
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/records-management-service_es.properties
@@ -0,0 +1,17 @@
+rm.service.error-add-content-container=No se puede a\u00f1adir contenido a un contenedor de registros. Use carpetas de registro para archivar contenido.
+rm.service.update-disposition-action-def=No se ha podido actualizar la definici\u00f3n de acci\u00f3n de disposici\u00f3n porque se est\u00e1 publicando una actualizaci\u00f3n.
+rm.service.set-id=No se puede establecer el valor de la propiedad de identificador del objeto {0} porque es de solo lectura.
+rm.service.path-node=No se pudo obtener la ruta del nodo. (nodeRef={0})
+rm.service.invalid-rm-node=Nodo de gesti\u00f3n de registros no v\u00e1lido porque el aspecto {0} no est\u00e1 presente.
+rm.service.no-root=No se pudo encontrar la ra\u00edz de gesti\u00f3n de registros.
+rm.service.dup-root=No se puede crear la ra\u00edz de gesti\u00f3n de registros porque ya existe una en esta jerarqu\u00eda.
+rm.service.root-type=No se puede crear la ra\u00edz de gesti\u00f3n de registros porque el tipo {0} no es un subtipo de rm:recordsManagementRootContainer.
+rm.service.container-parent-type=No se puede crear un contenedor de gesti\u00f3n de registros porque el padre no es un subtipo de rm:recordsManagement (parentType={0})
+rm.service.container-type=No se puede crear un contenedor de gesti\u00f3n de registros porque el tipo {0} no es un subtipo de rm:recordsManagementContainer.
+rm.service.container-expected=Referencia de nodo a un rm:recordsManagementContainer nodo esperado.
+rm.service.record-folder-expected=Referencia de nodo a un rm:recordFolder nodo esperado.
+rm.service.parent-record-folder-root=No se puede crear una carpeta de registros porque el padre es una ra\u00edz de gesti\u00f3n de registros.
+rm.service.parent-record-folder-type=No se puede crear una carpeta de registros porque el padre no era un subtipo de rm:recordsManagementContainer. (parentType={0})
+rm.service.record-folder-type=No se puede crear una carpeta de registros porque el tipo proporcionado no es un subtipo de rm:recordFolder. (type={0})
+rm.service.not-record=El nodo {0} no es un registro.
+rm.service.vital-def-missing=Aspecto de definici\u00f3n de registro vital no est\u00e1 presente en el nodo. (nodeRef={0})
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/records-model_es.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/records-model_es.properties
new file mode 100644
index 0000000000..ecc2304606
--- /dev/null
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/messages/records-model_es.properties
@@ -0,0 +1,276 @@
+rma_recordsmanagement.description=Modelo de contenido de gesti\u00f3n de registros
+
+rma_recordsmanagement.type.rma_rmsite.title=Sitio de gesti\u00f3n de registros
+rma_recordsmanagement.type.rma_rmsite.description=Sitio especializado para gesti\u00f3n de registros
+
+rma_recordsmanagement.type.rma_caveatConfig.title=Configuraci\u00f3n de advertencia
+rma_recordsmanagement.type.rma_caveatConfig.decription=Configuraci\u00f3n de advertencia
+
+rma_recordsmanagement.type.rma_emailConfig.title=Configuraci\u00f3n de correo electr\u00f3nico
+rma_recordsmanagement.type.rma_emailConfig.decription=Configuraci\u00f3n de correo electr\u00f3nico
+
+rma_recordsmanagement.type.rma_recordsManagementContainer.title=Contenedor de gesti\u00f3n de registros
+rma_recordsmanagement.type.rma_recordsManagementContainer.decription=Contenedor de gesti\u00f3n de registros
+
+rma_recordsmanagement.type.rma_recordsManagementRootContainer.title=Contenedor de ra\u00edz de gesti\u00f3n de registros
+rma_recordsmanagement.type.rma_recordsManagementRootContainer.decription=Contenedor de ra\u00edz de gesti\u00f3n de registros
+
+rma_recordsmanagement.type.rma_dispositionSchedule.title=Planificaci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.type.rma_dispositionSchedule.decription=Planificaci\u00f3n de disposici\u00f3n
+
+rma_recordsmanagement.property.rma_dispositionAuthority.title=Autoridad de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionAuthority.decription=Autoridad de disposici\u00f3n
+
+rma_recordsmanagement.property.rma_dispositionInstructions.title=Instrucciones de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionInstructions.decription=Instrucciones de disposici\u00f3n
+
+rma_recordsmanagement.property.rma_recordLevelDisposition.title=Disposici\u00f3n de nivel de registro
+rma_recordsmanagement.property.rma_recordLevelDisposition.decription=Disposici\u00f3n de nivel de registro
+
+rma_recordsmanagement.association.rma_dispositionActionDefinitions.title=Acciones de disposici\u00f3n
+rma_recordsmanagement.association.rma_dispositionActionDefinitions.decription=Acciones de disposici\u00f3n
+
+rma_recordsmanagement.type.rma_dispositionActionDefinition.title=Definici\u00f3n de acciones de disposici\u00f3n
+rma_recordsmanagement.type.rma_dispositionActionDefinition.decription=Definici\u00f3n de acciones de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionActionName.title=Nombre de acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionActionName.decription=Nombre de acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionDescription.title=Descripci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionDescription.decription=Descripci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionLocation.title=Ubicaci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionLocation.decription=Ubicaci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionPeriod.title=Per\u00edodo de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionPeriod.decription=Per\u00edodo de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionPeriodProperty.title=Propiedad de per\u00edodo de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionPeriodProperty.decription=Propiedad de per\u00edodo de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionEvent.title=Evento de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionEvent.decription=Evento de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionEventCombination.title=Combinaci\u00f3n de evento de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionEventCombination.decription=Combinaci\u00f3n de evento de disposici\u00f3n
+
+rma_recordsmanagement.type.rma_recordFolder.title=Carpeta de registros
+rma_recordsmanagement.type.rma_recordFolder.decription=Carpeta de registros
+rma_recordsmanagement.property.rma_isClosed.title=Registro
+rma_recordsmanagement.property.rma_isClosed.decription=Registro
+
+rma_recordsmanagement.type.rma_nonElectronicDocument.title=Documento no electr\u00f3nico
+rma_recordsmanagement.type.rma_nonElectronicDocument.decription=Documento no electr\u00f3nico
+rma_recordsmanagement.property.rma_physicalSize.title=Tama\u00f1o f\u00edsico
+rma_recordsmanagement.property.rma_physicalSize.decription=El tama\u00f1o del documento en metros lineales
+rma_recordsmanagement.property.rma_numberOfCopies.title=N\u00famero de copias
+rma_recordsmanagement.property.rma_numberOfCopies.description=El n\u00famero de copias del documento
+rma_recordsmanagement.property.rma_storageLocation.title=Ubicaci\u00f3n de almacenamiento
+rma_recordsmanagement.property.rma_storageLocation.decription=La ubicaci\u00f3n f\u00edsica del registro.
+rma_recordsmanagement.property.rma_shelf.title=Estanter\u00eda
+rma_recordsmanagement.property.rma_shelf.decription=La estanter\u00eda en la que reside el registro.
+rma_recordsmanagement.property.rma_box.title=Caja
+rma_recordsmanagement.property.rma_box.description=La caja en el que reside el registro.
+rma_recordsmanagement.property.rma_file.title=Archivo o carpeta
+rma_recordsmanagement.property.rma_file.decription=El fichero en el que reside el registro.
+
+rma_recordsmanagement.type.rma_dispositionAction.title=Acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.type.rma_dispositionAction.decription=Acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionActionId.title=Id de acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionActionId.decription=Id de acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionAction.title=Acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionAction.decription=Acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionAsOf.title=Acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionAsOf.decription=Acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_dispositionEventsEligible.title=Eventos de disposici\u00f3n elegibles
+rma_recordsmanagement.property.rma_dispositionEventsEligible.decription=Eventos de disposici\u00f3n elegibles
+rma_recordsmanagement.property.rma_dispositionActionStartedAt.title=Acci\u00f3n de disposici\u00f3n iniciada en
+rma_recordsmanagement.property.rma_dispositionActionStartedAt.decription=Acci\u00f3n de disposicion iniciada en
+rma_recordsmanagement.property.rma_dispositionActionStartedBy.title=Acci\u00f3n de disposici\u00f3n iniciada por
+rma_recordsmanagement.property.rma_dispositionActionStartedBy.decription=Acci\u00f3n de disposici\u00f3n iniciada por
+rma_recordsmanagement.property.rma_dispositionActionCompletedAt.title=Acci\u00f3n de disposici\u00f3n completada en
+rma_recordsmanagement.property.rma_dispositionActionCompletedAt.decription=Acci\u00f3n de disposici\u00f3n completada en
+rma_recordsmanagement.property.rma_dispositionActionCompletedBy.title=Acci\u00f3n de disposici\u00f3n completada por
+rma_recordsmanagement.property.rma_dispositionActionCompletedBy.decription=Acci\u00f3n de disposici\u00f3n completada por
+rma_recordsmanagement.association.rma_eventExecutions.title=Ejecuciones de evento
+rma_recordsmanagement.association.rma_eventExecutions.decription=Ejecuciones de evento
+
+rma_recordsmanagement.type.rma_eventExecution.title=Ejecuci\u00f3n de evento
+rma_recordsmanagement.type.rma_eventExecution.decription=Ejecuci\u00f3n de evento
+rma_recordsmanagement.property.rma_eventExecutionName.title=Nombre de evento
+rma_recordsmanagement.property.rma_eventExecutionName.decription=Nombre de evento
+rma_recordsmanagement.property.rma_eventExecutionAutomatic.title=Evento autom\u00e1tico
+rma_recordsmanagement.property.rma_eventExecutionAutomatic.decription=Evento autom\u00e1tico
+rma_recordsmanagement.property.rma_eventExecutionComplete.title=Evento completo
+rma_recordsmanagement.property.rma_eventExecutionComplete.decription=Evento completo
+rma_recordsmanagement.property.rma_eventExecutionCompletedBy.title=Evento completado por
+rma_recordsmanagement.property.rma_eventExecutionCompletedBy.decription=Evento completado por
+rma_recordsmanagement.property.rma_eventExecutionCompletedAt.title=Evento completado en
+rma_recordsmanagement.property.rma_eventExecutionCompletedAt.decription=Evento completado en
+
+rma_recordsmanagement.type.rma_hold.title=Bloqueo
+rma_recordsmanagement.type.rma_hold.decription=Bloqueo
+rma_recordsmanagement.property.rma_holdReason.title=Raz\u00f3n de bloqueo
+rma_recordsmanagement.property.rma_holdReason.decription=Raz\u00f3n de bloqueo
+rma_recordsmanagement.association.rma_frozenRecords.title=Registros fijados
+rma_recordsmanagement.association.rma_frozenRecords.decription=Registros fijados
+
+rma_recordsmanagement.type.rma_transfer.title=Transferencia
+rma_recordsmanagement.type.rma_transfer.decription=Transferencia
+rma_recordsmanagement.property.rma_transferAccessionIndicator.title=Indicador de acceso de transferencia
+rma_recordsmanagement.property.rma_transferAccessionIndicator.decription=Indicador de acceso de transferencia
+rma_recordsmanagement.property.rma_transferPDFIndicator.title=Indicador de transferencia de PDF
+rma_recordsmanagement.property.rma_transferPDFIndicator.decription=Indicador de transferencia de PDF
+rma_recordsmanagement.property.rma_transferLocation.title=Transferencia de PDF
+rma_recordsmanagement.property.rma_transferLocation.decription=Transferencia de PDF
+rma_recordsmanagement.association.rma_transferred.title=Transferido
+rma_recordsmanagement.association.rma_transferred.decription=Transferido
+
+rma_recordsmanagement.aspect.rma_filePlanComponent.title=Componente del plan de archivo
+rma_recordsmanagement.aspect.rma_filePlanComponent.decription=Componente del plan de archivo
+rma_recordsmanagement.property.rma_rootNodeRef.title=Nodo ra\u00edz
+rma_recordsmanagement.property.rma_rootNodeRef.decription=Nodo ra\u00edz
+
+rma_recordsmanagement.aspect.rma_recordsManagementRoot.title=Ra\u00edz de gesti\u00f3n de registros
+rma_recordsmanagement.aspect.rma_recordsManagementRoot.decription=Ra\u00edz de gesti\u00f3n de registros
+rma_recordsmanagement.association.rma_holds.title=Bloqueos
+rma_recordsmanagement.association.rma_holds.decription=Bloqueos
+rma_recordsmanagement.association.rma_transfers.title=Transferencias
+rma_recordsmanagement.association.rma_transfers.decription=Transferencias
+
+rma_recordsmanagement.aspect.rma_declaredRecord.title=Registro declarado
+rma_recordsmanagement.aspect.rma_declaredRecord.decription=Registro declarado
+rma_recordsmanagement.property.rma_declaredAt.title=Fecha declarada
+rma_recordsmanagement.property.rma_declaredAt.decription=Fecha declarada
+rma_recordsmanagement.property.rma_declaredBy.title=Declarado por
+rma_recordsmanagement.property.rma_declaredBy.decription=Declarado por
+
+rma_recordsmanagement.aspect.rma_recordComponentIdentifier.title=Identificador de componente de registro
+rma_recordsmanagement.aspect.rma_recordComponentIdentifier.decription=Identificador de componente de registro
+rma_recordsmanagement.property.rma_identifier.title=Identificador
+rma_recordsmanagement.property.rma_identifier.decription=Identificador \u00fanico de registro
+rma_recordsmanagement.property.rma_dbUniquenessId.title=Unicidad de la base de datos
+rma_recordsmanagement.property.rma_dbUniquenessId.decription=Unicidad de la base de datos
+
+rma_recordsmanagement.aspect.rma_vitalRecordDefinition.title=Definici\u00f3n de registro vital
+rma_recordsmanagement.aspect.rma_vitalRecordDefinition.decription=Definici\u00f3n de registro vital
+
+rma_recordsmanagement.property.rma_reviewPeriod.title=Per\u00edodo de revisi\u00f3n
+rma_recordsmanagement.property.rma_reviewPeriod.decription=Per\u00edodo de revisi\u00f3n
+rma_recordsmanagement.property.rma_vitalRecordIndicator.title=Indicador de registro vital
+rma_recordsmanagement.property.rma_vitalRecordIndicator.decription=Indicador de registro vital
+
+rma_recordsmanagement.aspect.rma_record.title=Registro
+rma_recordsmanagement.aspect.rma_record.decription=Registro
+rma_recordsmanagement.property.rma_dateFiled.title=Fecha de archivado
+rma_recordsmanagement.property.rma_dateFiled.decription=Fecha de archivado
+rma_recordsmanagement.property.rma_publicationDate.title=Fecha de publicaci\u00f3n
+rma_recordsmanagement.property.rma_publicationDate.decription=Fecha de publicaci\u00f3n
+rma_recordsmanagement.property.rma_originator.title=Creador
+rma_recordsmanagement.property.rma_originator.decription=Creador
+rma_recordsmanagement.property.rma_originatingOrganization.title=Organizaci\u00f3n creadora
+rma_recordsmanagement.property.rma_originatingOrganization.decription=Organizaci\u00f3n creadora
+rma_recordsmanagement.property.rma_mediaType.title=Tipo de medio
+rma_recordsmanagement.property.rma_mediaType.decription=Tipo de medio
+rma_recordsmanagement.property.rma_format.title=Formato
+rma_recordsmanagement.property.rma_format.decription=Formato
+rma_recordsmanagement.property.rma_dateReceived.title=Fecha de recepci\u00f3n
+rma_recordsmanagement.property.rma_dateReceived.decription=Fecha de recepci\u00f3n
+rma_recordsmanagement.property.rma_address.title=Destinatario
+rma_recordsmanagement.property.rma_address.decription=Destinatario
+rma_recordsmanagement.property.rma_otherAddress.title=Otro destinatario
+rma_recordsmanagement.property.rma_otherAddress.decription=Otro destinatario
+
+rma_recordsmanagement.aspect.rma_recordMetaData.title=Registro de metadatos
+rma_recordsmanagement.aspect.rma_recordMetaData.description=Aspecto de marcador para registro de metadatos
+
+rma_recordsmanagement.aspect.rma_commonRecordDetails.title=Detalles de registro com\u00fan
+rma_recordsmanagement.aspect.rma_commonRecordDetails.description=Metadatos comunes a todos los tipos de registro
+rma_recordsmanagement.property.rma_location.title=Ubicaci\u00f3n
+rma_recordsmanagement.property.rma_location.decription=Ubicaci\u00f3n
+
+rma_recordsmanagement.aspect.rma_vitalRecord.title=Registro vital
+rma_recordsmanagement.aspect.rma_vitalRecord.decription=Registro vital
+rma_recordsmanagement.property.rma_reviewAsOf.title=Pr\u00f3xima revisi\u00f3n
+rma_recordsmanagement.property.rma_reviewAsOf.decription=Pr\u00f3xima revisi\u00f3n
+rma_recordsmanagement.property.rma_notificationIssued.title=Indica n que este registro est\u00e1 pendiente de revis\u00f3n ha sido expedido
+rma_recordsmanagement.property.rma_notificationIssued.decription=Indica n que este registro est\u00e1 pendiente de revis\u00f3n ha sido expedido
+
+rma_recordsmanagement.aspect.rma_scheduled.title=Planificado
+rma_recordsmanagement.aspect.rma_scheduled.decription=Planificado
+rma_recordsmanagement.association.rma_dispositionSchedule.title=Planificaci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.association.rma_dispositionSchedule.decription=Planificaci\u00f3n de disposici\u00f3n
+
+rma_recordsmanagement.aspect.rma_dispositionLifecycle.title=Ciclo de vida de disposici\u00f3n
+rma_recordsmanagement.aspect.rma_dispositionLifecycle.decription=Ciclo de vida de disposici\u00f3n
+rma_recordsmanagement.association.rma_nextDispositionAction.title=Pr\u00f3xima acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.association.rma_nextDispositionAction.decription=Pr\u00f3xima acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.association.rma_dispositionActionHistory.title=Historial de acciones de disposici\u00f3n
+rma_recordsmanagement.association.rma_dispositionActionHistory.decription=Historial de acciones de disposici\u00f3n
+
+rma_recordsmanagement.aspect.rma_cutOff.title=Interrumpir
+rma_recordsmanagement.aspect.rma_cutOff.decription=Interrumpir
+rma_recordsmanagement.property.rma_cutOffDate.title=Fecha de interrupci\u00f3n
+rma_recordsmanagement.property.rma_cutOffDate.decription=Fecha de interrupci\u00f3n
+
+rma_recordsmanagement.aspect.rma_transferred.title=Transferido
+rma_recordsmanagement.aspect.rma_transferred.decription=Transferido
+
+rma_recordsmanagement.aspect.rma_ascended.title=Acendido
+rma_recordsmanagement.aspect.rma_ascended.decription=Ascendido
+
+rma_recordsmanagement.aspect.rma_frozen.title=Fijado
+rma_recordsmanagement.aspect.rma_frozen.decription=Fijado
+rma_recordsmanagement.property.rma_frozenAt.title=Fijado en
+rma_recordsmanagement.property.rma_frozenAt.decription=Fijado en
+rma_recordsmanagement.property.rma_frozenBy.title=Fijado por
+rma_recordsmanagement.property.rma_frozenBy.decription=Fijado por
+
+rma_recordsmanagement.aspect.rma_caveatConfigRoot.title=Ra\u00edz de configuraci\u00f3n de advertencia
+rma_recordsmanagement.aspect.rma_caveatConfigRoot.decription=Ra\u00edz de configuraci\u00f3n de advertencia
+rma_recordsmanagement.association.rma_caveatConfigAssoc.title=Configuraci\u00f3n de advertencia
+rma_recordsmanagement.association.rma_caveatConfigAssoc.description=Configuraci\u00f3n de advertencia
+
+rma_recordsmanagement.aspect.rma_emailConfigRoot.title=Ra\u00edz de configuraci\u00f3n de correo electr\u00f3nico
+rma_recordsmanagement.aspect.rma_emailConfigRoot.decription=Ra\u00edz de configuraci\u00f3n de correo electr\u00f3nico
+rma_recordsmanagement.association.rma_emailConfigAssoc.title=Configuraci\u00f3n de correo electr\u00f3nico
+rma_recordsmanagement.association.rma_emailConfigAssoc.description=Configuraci\u00f3n de correo electr\u00f3nico
+
+rma_recordsmanagement.aspect.rma_recordSearch.title=B\u00fasqueda de registros
+rma_recordsmanagement.aspect.rma_recordSearch.decription=Informaci\u00f3n de b\u00fasqueda enrollada a b\u00fasqueda de gesti\u00f3n de registros
+rma_recordsmanagement.property.rma_recordSearchHasDispositionSchedule.title=Tiene planificaci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchHasDispositionSchedule.description=Indica si el elemento tiene planificaci\u00f3n de disposici\u00f3n asociada
+rma_recordsmanagement.property.rma_recordSearchDispositionActionName.title=Nombre de acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionActionName.description=El nombre de la siguiente acci\u00f3n de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionActionAsOf.title=Acci\u00f3n de disposici\u00f3n de
+rma_recordsmanagement.property.rma_recordSearchDispositionActionAsOf.description=La fecha en la cual la pr\u00f3xima acci\u00f3n de disposici\u00f3n se hace elegible
+rma_recordsmanagement.property.rma_recordSearchDispositionPeriod.title=Per\u00edodo de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionPeriod.description=Per\u00edodo de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionPeriodExpression.title=Expresi\u00f3n de per\u00edodo de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionPeriodExpression.description=Expresi\u00f3n de per\u00edodo de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionEventsEligible.title=Eventos de disposici\u00f3n elegibles
+rma_recordsmanagement.property.rma_recordSearchDispositionEventsEligible.description=Eventos de disposici\u00f3n elegibles
+rma_recordsmanagement.property.rma_recordSearchDispositionEvents.title=Eventos de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionEvents.description=Eventos de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionAuthority.title=Autoridad de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionAuthority.description=Autoridad de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionInstructions.title=Instrucciones de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchDispositionInstructions.description=Instrucciones de disposici\u00f3n
+rma_recordsmanagement.property.rma_recordSearchHoldReason.title=Raz\u00f3n de bloqueo
+rma_recordsmanagement.property.rma_recordSearchHoldReason.description=Raz\u00f3n de bloqueo
+rma_recordsmanagement.property.rma_recordSearchVitalRecordReviewPeriod.title=Per\u00edodo de revisi\u00f3n de registro vital
+rma_recordsmanagement.property.rma_recordSearchVitalRecordReviewPeriod.description=Per\u00edodo de revisi\u00f3n de registro vital
+rma_recordsmanagement.property.rma_recordSearchVitalRecordReviewPeriodExpression.title=Expresi\u00f3n de per\u00edodo de revisi\u00f3n
+rma_recordsmanagement.property.rma_recordSearchVitalRecordReviewPeriodExpression.description=Expresi\u00f3n de per\u00edodo de revisi\u00f3n
+
+rma_recordsmanagement.aspect.rma_versionedRecord.title=Registro versionado
+rma_recordsmanagement.aspect.rma_versionedRecord.decription=Registro versionado
+
+rma_recordsmanagement.aspect.rma_unpublishedUpdate.title=Actualizaci\u00f3n sin publicar
+rma_recordsmanagement.aspect.rma_unpublishedUpdate.decription=Actualizaci\u00f3n sin publicar
+rma_recordsmanagement.property.rma_unpublishedUpdate.title=Actualizaci\u00f3n sin publicar
+rma_recordsmanagement.property.rma_unpublishedUpdate.description=Indica si existe una actualizaci\u00f3n sin publicar
+rma_recordsmanagement.property.rma_updateTo.title=Actualizar a
+rma_recordsmanagement.property.rma_updateTo.description=Destino de la actualizaci\u00f3n
+rma_recordsmanagement.property.rma_updatedProperties.title=Propiedades actualizadas
+rma_recordsmanagement.property.rma_updatedProperties.description=Las propiedades actualizadas
+rma_recordsmanagement.property.rma_publishInProgress.title=Publicaci\u00f3n en progreso
+rma_recordsmanagement.property.rma_publishInProgress.description=Indica si una publicaci\u00f3n se encuentra en progreso
+
+rma_recordsmanagement.aspect.dod_ghosted.title=Registro escrito por otro
+rma_recordsmanagement.aspect.dod_ghosted.description=Registro escrito por otro
+
+
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/module.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/module.properties
index 9d1f77120e..22b955cd83 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/module.properties
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/module.properties
@@ -6,6 +6,6 @@ module.aliases=org_alfresco_module_dod5015
module.title=Records Management
module.description=Alfresco Record Management Extension
-module.version=2.0
+module.version=2.0.1
module.repo.version.min=4.0.2
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-events.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-events.properties
index 354503dbdd..076458a281 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-events.properties
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-events.properties
@@ -2,4 +2,4 @@
rmeventservice.rmEventType.simple=Simple Event
rmeventservice.rmEventType.obsolete=Obsoleted Event
rmeventservice.rmEventType.superseded=Superseded Event
-rmeventservice.rmEventType.crossReferencedRecordTransfered=Cross Referenced Record Transfered
\ No newline at end of file
+rmeventservice.rmEventType.crossReferencedRecordTransfered=Cross Referenced Record Transffered
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-job-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-job-context.xml
index eb2184ea87..8aed3a4137 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-job-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-job-context.xml
@@ -2,6 +2,11 @@
+
+
+
+
+
@@ -23,13 +28,14 @@
-
+
-
+
-
@@ -45,7 +51,7 @@
-
+
org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJob
@@ -63,13 +69,14 @@
-
+
-
-
+
@@ -83,7 +90,7 @@
-
+ org.alfresco.module.org_alfresco_module_rm.job.RecordsManagementJob
@@ -99,7 +106,7 @@
-
+
@@ -109,10 +116,11 @@
-
+
-
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml
index ecf38df976..5c3e60b334 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-public-services-security-context.xml
@@ -172,232 +172,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
index 930ba708fd..a6d9d1fef9 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml
@@ -613,6 +613,7 @@
org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService.addEvent=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService.removeEvent=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService.existsEvent=RM_ALLOW
+ org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService.existsEventDisplayLabel=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService.*=RM_DENY
]]>
@@ -989,7 +990,8 @@
-
+
+
diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
index 1e4b5290be..a0ec3f5b4e 100644
--- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
+++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-ui-evaluators-context.xml
@@ -523,7 +523,14 @@
-
+
+
+ FILE_PLAN
+ RECORD_CATEGORY
+ RECORD_FOLDER
+
+
+
{
- "data":
- {
- "url": "${nextaction.url}",
- "name": "${nextaction.name}",
- "label": "${nextaction.label}",
- "eventsEligible": ${nextaction.eventsEligible?string},
- <#if nextaction.asOf??>"asOf": "${nextaction.asOf}",#if>
- <#if nextaction.startedAt??>"startedAt": "${nextaction.startedAt}",#if>
- <#if nextaction.startedBy??>"startedBy": "${nextaction.startedBy}",#if>
- <#if nextaction.startedByFirstName??>"startedByFirstName": "${nextaction.startedByFirstName}",#if>
- <#if nextaction.startedByLastName??>"startedByLastName": "${nextaction.startedByLastName}",#if>
- <#if nextaction.completedAt??>"completedAt": "${nextaction.completedAt}",#if>
- <#if nextaction.completedBy??>"completedBy": "${nextaction.completedBy}",#if>
- <#if nextaction.completedByFirstName??>"completedByFirstName": "${nextaction.completedByFirstName}",#if>
- <#if nextaction.completedByLastName??>"completedByLastName": "${nextaction.completedByLastName}",#if>
- "events":
- [
- <#list nextaction.events as event>
- {
- "name": "${event.name}",
- "label": "${event.label}",
- "complete": ${event.complete?string},
- <#if event.completedAt??>"completedAt": "${event.completedAt}",#if>
- <#if event.completedBy??>"completedBy": "${event.completedBy}",#if>
- <#if event.completedByFirstName??>"completedByFirstName": "${event.completedByFirstName}",#if>
- <#if event.completedByLastName??>"completedByLastName": "${event.completedByLastName}",#if>
- "automatic": ${event.automatic?string}
- }<#if event_has_next>,#if>
- #list>
- ]
- }
+ "data":
+ {
+ <#if nextaction.notFound?? && nextaction.notFound>
+ "notFound": ${nextaction.notFound?string},
+ "message": "${nextaction.message}"
+ <#else>
+ "url": "${nextaction.url}",
+ "name": "${nextaction.name}",
+ "label": "${nextaction.label}",
+ "eventsEligible": ${nextaction.eventsEligible?string},
+ <#if nextaction.asOf??>"asOf": "${nextaction.asOf}",#if>
+ <#if nextaction.startedAt??>"startedAt": "${nextaction.startedAt}",#if>
+ <#if nextaction.startedBy??>"startedBy": "${nextaction.startedBy}",#if>
+ <#if nextaction.startedByFirstName??>"startedByFirstName": "${nextaction.startedByFirstName}",#if>
+ <#if nextaction.startedByLastName??>"startedByLastName": "${nextaction.startedByLastName}",#if>
+ <#if nextaction.completedAt??>"completedAt": "${nextaction.completedAt}",#if>
+ <#if nextaction.completedBy??>"completedBy": "${nextaction.completedBy}",#if>
+ <#if nextaction.completedByFirstName??>"completedByFirstName": "${nextaction.completedByFirstName}",#if>
+ <#if nextaction.completedByLastName??>"completedByLastName": "${nextaction.completedByLastName}",#if>
+ "events":
+ [
+ <#list nextaction.events as event>
+ {
+ "name": "${event.name}",
+ "label": "${event.label}",
+ "complete": ${event.complete?string},
+ <#if event.completedAt??>"completedAt": "${event.completedAt}",#if>
+ <#if event.completedBy??>"completedBy": "${event.completedBy}",#if>
+ <#if event.completedByFirstName??>"completedByFirstName": "${event.completedByFirstName}",#if>
+ <#if event.completedByLastName??>"completedByLastName": "${event.completedByLastName}",#if>
+ "automatic": ${event.automatic?string}
+ }<#if event_has_next>,#if>
+ #list>
+ ]
+ #if>
+ }
}
#escape>
\ No newline at end of file
diff --git a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/doclist.lib.js b/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/doclist.lib.js
deleted file mode 100644
index 947666762f..0000000000
--- a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/doclist.lib.js
+++ /dev/null
@@ -1,264 +0,0 @@
-const REQUEST_MAX = 1000;
-
-/**
- * Main entry point: Create collection of documents and folders in the given space
- *
- * @method doclist_main
- */
-function doclist_main()
-{
- // Use helper function to get the arguments
- var parsedArgs = ParseArgs.getParsedArgs();
- if (parsedArgs === null)
- {
- return;
- }
-
- var filter = args.filter,
- items = [];
-
- // Try to find a filter query based on the passed-in arguments
- var allNodes = [],
- totalRecords = 0,
- requestTotalCountMax = 0,
- paged = false,
- favourites = Common.getFavourites(),
- filterParams = Filters.getFilterParams(filter, parsedArgs,
- {
- favourites: favourites
- }),
- query = filterParams.query;
-
- if ((filter || "path") == "path")
- {
- // TODO also add DB filter by "node" (in addition to "path")
- var parentNode = parsedArgs.pathNode;
- if (parentNode !== null)
- {
- var skip = -1,
- max = -1;
-
- if (args.size != null)
- {
- max = args.size;
-
- if (args.pos > 0)
- {
- skip = (args.pos - 1) * max;
- }
- }
-
- var sortField = (args.sortField == null ? "cm:name" : args.sortField),
- sortAsc = (((args.sortAsc == null) || (args.sortAsc == "true")) ? true : false);
-
- // Get paged set
- requestTotalCountMax = skip + REQUEST_MAX;
- var pagedResult = parentNode.childFileFolders(true, true, filterParams.ignoreTypes, skip, max, requestTotalCountMax, sortField, sortAsc, "TODO");
-
- allNodes = pagedResult.page;
- totalRecords = pagedResult.totalResultCountUpper;
- paged = true;
- }
- }
- else
- {
- // Query the nodes - passing in sort and result limit parameters
- if (query !== "")
- {
- allNodes = search.query(
- {
- query: query,
- language: filterParams.language,
- page:
- {
- maxItems: (filterParams.limitResults ? parseInt(filterParams.limitResults, 10) : 0)
- },
- sort: filterParams.sort,
- templates: filterParams.templates,
- namespace: (filterParams.namespace ? filterParams.namespace : null)
- });
-
- totalRecords = allNodes.length;
- }
- }
-
- // Ensure folders and folderlinks appear at the top of the list
- var folderNodes = [],
- documentNodes = [];
-
- for each (node in allNodes)
- {
- try
- {
- if (node.isContainer || node.isLinkToContainer)
- {
- folderNodes.push(node);
- }
- else
- {
- documentNodes.push(node);
- }
- }
- catch (e)
- {
- // Possibly an old indexed node - ignore it
- }
- }
-
- // Node type counts
- var folderNodesCount = folderNodes.length,
- documentNodesCount = documentNodes.length,
- nodes;
-
- if (parsedArgs.type === "documents")
- {
- nodes = documentNodes;
- totalRecords -= folderNodesCount;
- }
- else
- {
- // TODO: Sorting with folders at end -- swap order of concat()
- nodes = folderNodes.concat(documentNodes);
- }
-
- // Pagination
- var pageSize = args.size || nodes.length,
- pagePos = args.pos || "1",
- startIndex = (pagePos - 1) * pageSize;
-
- if (!paged)
- {
- // Trim the nodes array down to the page size
- nodes = nodes.slice(startIndex, pagePos * pageSize);
- }
-
- // Common or variable parent container?
- var parent = null;
-
- if (!filterParams.variablePath)
- {
- // Parent node permissions (and Site role if applicable)
- parent = Evaluator.run(parsedArgs.pathNode, true);
- }
-
- var isThumbnailNameRegistered = thumbnailService.isThumbnailNameRegistered(THUMBNAIL_NAME),
- thumbnail = null,
- locationNode,
- item;
-
- // Loop through and evaluate each node in this result set
- for each (node in nodes)
- {
- // Get evaluated properties.
- item = Evaluator.run(node);
- if (item !== null)
- {
- item.isFavourite = (favourites[item.node.nodeRef] === true);
- item.likes = Common.getLikes(node);
-
- // Does this collection of nodes have potentially differering paths?
- if (filterParams.variablePath || item.isLink)
- {
- locationNode = item.isLink ? item.linkedNode : item.node;
- location = Common.getLocation(locationNode, parsedArgs.libraryRoot);
- // Parent node
- if (node.parent != null &&
- (node.parent.hasPermission("Read") || node.parent.hasPermission("ReadRecords")))
- {
- item.parent = Evaluator.run(node.parent, true);
- }
- }
- else
- {
- location =
- {
- site: parsedArgs.location.site,
- siteTitle: parsedArgs.location.siteTitle,
- sitePreset: parsedArgs.location.sitePreset,
- container: parsedArgs.location.container,
- containerType: parsedArgs.location.containerType,
- path: parsedArgs.location.path,
- file: node.name
- };
- }
-
- // Resolved location
- item.location = location;
-
- // Check: thumbnail type is registered && node is a cm:content subtype && valid inputStream for content property
- if (isThumbnailNameRegistered && item.node.isSubType("cm:content") && item.node.properties.content.inputStream != null)
- {
- // Make sure we have a thumbnail.
- thumbnail = item.node.getThumbnail(THUMBNAIL_NAME);
- if (thumbnail === null)
- {
- // No thumbnail, so queue creation
- item.node.createThumbnail(THUMBNAIL_NAME, true);
- }
- }
-
- items.push(item);
- }
- else
- {
- --totalRecords;
- }
- }
-
- // Array Remove - By John Resig (MIT Licensed)
- var fnArrayRemove = function fnArrayRemove(array, from, to)
- {
- var rest = array.slice((to || from) + 1 || array.length);
- array.length = from < 0 ? array.length + from : from;
- return array.push.apply(array, rest);
- };
-
- /**
- * De-duplicate orignals for any existing working copies.
- * This can't be done in evaluator.lib.js as it has no knowledge of the current filter or UI operation.
- * Note: This may result in pages containing less than the configured amount of items (50 by default).
- */
- for each (item in items)
- {
- if (item.workingCopy.isWorkingCopy)
- {
- var workingCopySource = String(item.workingCopy.sourceNodeRef);
- for (var i = 0, ii = items.length; i < ii; i++)
- {
- if (String(items[i].node.nodeRef) == workingCopySource)
- {
- fnArrayRemove(items, i);
- --totalRecords;
- break;
- }
- }
- }
- }
-
- var paging =
- {
- totalRecords: totalRecords,
- startIndex: startIndex
- };
-
- if (paged && (totalRecords == requestTotalCountMax))
- {
- paging.totalRecordsUpper = requestTotalCountMax;
- }
-
- return (
- {
- luceneQuery: query,
- paging: paging,
- container: parsedArgs.rootNode,
- parent: parent,
- onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"),
- itemCount:
- {
- folders: folderNodesCount,
- documents: documentNodesCount
- },
- items: items,
- customJSON: slingshotDocLib.getJSON()
- });
-}
diff --git a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/node.get.js b/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/node.get.js
deleted file mode 100644
index 145314fb8c..0000000000
--- a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary-v2/node.get.js
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-/**
- * Main entry point: Return single document or folder given it's nodeRef
- *
- * @method getDoclist
- */
-function getDoclist()
-{
- // Use helper function to get the arguments
- var parsedArgs = ParseArgs.getParsedArgs();
- if (parsedArgs === null)
- {
- return;
- }
-
- parsedArgs.pathNode = ParseArgs.resolveNode(parsedArgs.nodeRef);
- parsedArgs.location = Common.getLocation(parsedArgs.pathNode, parsedArgs.libraryRoot);
-
- var favourites = Common.getFavourites(),
- node = parsedArgs.pathNode;
-
- var isThumbnailNameRegistered = thumbnailService.isThumbnailNameRegistered(THUMBNAIL_NAME),
- thumbnail = null,
- item = Evaluator.run(node);
-
- item.isFavourite = (favourites[node.nodeRef] === true);
- item.likes = Common.getLikes(node);
- item.location =
- {
- site: parsedArgs.location.site,
- siteTitle: parsedArgs.location.siteTitle,
- container: parsedArgs.location.container,
- containerType: parsedArgs.location.containerType,
- path: parsedArgs.location.path,
- file: node.name
- };
-
- item.parent = {};
- if (node.parent != null && (node.parent.hasPermission("Read") || node.parent.hasPermission("ReadRecords")))
- {
- item.parent = Evaluator.run(node.parent, true);
- }
-
- // Special case for container and libraryRoot nodes
- if ((parsedArgs.location.containerNode && String(parsedArgs.location.containerNode.nodeRef) == String(node.nodeRef)) ||
- (parsedArgs.libraryRoot && String(parsedArgs.libraryRoot.nodeRef) == String(node.nodeRef)))
- {
- item.location.file = "";
- }
-
- // Check: thumbnail type is registered && node is a cm:content subtype && valid inputStream for content property
- if (isThumbnailNameRegistered && item.node.isSubType("cm:content") && item.node.properties.content.inputStream != null)
- {
- // Make sure we have a thumbnail.
- thumbnail = item.node.getThumbnail(THUMBNAIL_NAME);
- if (thumbnail === null)
- {
- // No thumbnail, so queue creation
- item.node.createThumbnail(THUMBNAIL_NAME, true);
- }
- }
-
- return (
- {
- container: parsedArgs.rootNode,
- onlineEditing: utils.moduleInstalled("org.alfresco.module.vti"),
- item: item,
- customJSON: slingshotDocLib.getJSON()
- });
-}
-
-/**
- * Document List Component: doclist
- */
-model.doclist = getDoclist();
\ No newline at end of file
diff --git a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/action/move-to.post.json.js b/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/action/move-to.post.json.js
deleted file mode 100644
index 04e3a8906f..0000000000
--- a/rm-server/config/alfresco/templates/webscripts/org/alfresco/slingshot/documentlibrary/action/move-to.post.json.js
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-/**
- * Move multiple files action
- * @method POST
- */
-
-/**
- * Entrypoint required by action.lib.js
- *
- * @method runAction
- * @param p_params {object} Object literal containing files array
- * @return {object|null} object representation of action results
- */
-function runAction(p_params)
-{
- var results = [],
- destNode = p_params.destNode,
- files = p_params.files,
- parent = null,
- file, fileNode, result, nodeRef,
- fromSite;
-
- // Must have array of files
- if (!files || files.length == 0)
- {
- status.setCode(status.STATUS_BAD_REQUEST, "No files.");
- return;
- }
-
- for (file in files)
- {
- nodeRef = files[file];
- result =
- {
- nodeRef: nodeRef,
- action: "moveFile",
- success: false
- }
-
- try
- {
- fileNode = search.findNode(nodeRef);
- if (fileNode == null)
- {
- result.id = file;
- result.nodeRef = nodeRef;
- result.success = false;
- }
- else
- {
- if (p_params.parent && p_params.parent != null)
- {
- parent = search.findNode(p_params.parent);
- }
- result.id = fileNode.name;
- result.type = fileNode.isContainer ? "folder" : "document";
-
- // Retain the name of the site the node is currently in. Null if it's not in a site.
- fromSite = fileNode.siteShortName;
-
- // move the node
- result.success = fileNode.move(parent, destNode);
-
- if (result.success)
- {
- // If this was an inter-site move, we'll need to clean up the permissions on the node
- if (!fromSite.equals(fileNode.siteShortName))
- {
- siteService.cleanSitePermissions(fileNode);
- }
- }
- }
- }
- catch (e)
- {
- result.id = file;
- result.nodeRef = nodeRef;
- result.success = false;
- }
-
- results.push(result);
- }
-
- return results;
-}
-
-/* Bootstrap action script */
-main();
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementAdminServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementAdminServiceImpl.java
index 789ee3bb1e..e7c116d913 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementAdminServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementAdminServiceImpl.java
@@ -1127,6 +1127,12 @@ public class RecordsManagementAdminServiceImpl implements RecordsManagementAdmin
public QName addCustomAssocDefinition(String label)
{
ParameterCheck.mandatoryString("label", label);
+
+ // If this label is already taken...
+ if (existsLabel(label))
+ {
+ throw new IllegalArgumentException(I18NUtil.getMessage(MSG_REF_LABEL_IN_USE, label));
+ }
NodeRef modelRef = getCustomModelRef(""); // defaults to RM_CUSTOM_URI
M2Model deserializedModel = readCustomContentModel(modelRef);
@@ -1140,12 +1146,6 @@ public class RecordsManagementAdminServiceImpl implements RecordsManagementAdmin
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_UNKNOWN_ASPECT, aspectName));
}
- // If this label is already taken...
- if (getQNameForClientId(label) != null)
- {
- throw new IllegalArgumentException(I18NUtil.getMessage(MSG_REF_LABEL_IN_USE, label));
- }
-
QName generatedQName = this.generateQNameFor(label);
String generatedShortQName = generatedQName.toPrefixString(namespaceService);
@@ -1178,6 +1178,18 @@ public class RecordsManagementAdminServiceImpl implements RecordsManagementAdmin
return generatedQName;
}
+
+ private boolean existsLabel(String label)
+ {
+ for (AssociationDefinition associationDefinition : getCustomReferenceDefinitions().values())
+ {
+ if (associationDefinition.getTitle().equalsIgnoreCase(label))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
// note: currently RMC custom assocs only
public QName addCustomChildAssocDefinition(String source, String target)
@@ -1185,6 +1197,12 @@ public class RecordsManagementAdminServiceImpl implements RecordsManagementAdmin
ParameterCheck.mandatoryString("source", source);
ParameterCheck.mandatoryString("target", target);
+ String compoundID = this.getCompoundIdFor(source, target);
+ if (existsLabel(compoundID))
+ {
+ throw new IllegalArgumentException(I18NUtil.getMessage(MSG_REF_LABEL_IN_USE, compoundID));
+ }
+
NodeRef modelRef = getCustomModelRef(""); // defaults to RM_CUSTOM_URI
M2Model deserializedModel = readCustomContentModel(modelRef);
@@ -1197,12 +1215,6 @@ public class RecordsManagementAdminServiceImpl implements RecordsManagementAdmin
throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_UNKNOWN_ASPECT, aspectName));
}
- String compoundID = this.getCompoundIdFor(source, target);
- if (getQNameForClientId(compoundID) != null)
- {
- throw new IllegalArgumentException(I18NUtil.getMessage(MSG_REF_LABEL_IN_USE, compoundID));
- }
-
M2ClassAssociation customAssoc = customAssocsAspect.getAssociation(compoundID);
if (customAssoc != null)
{
@@ -1238,13 +1250,23 @@ public class RecordsManagementAdminServiceImpl implements RecordsManagementAdmin
public QName updateCustomChildAssocDefinition(QName refQName, String newSource, String newTarget)
{
String compoundId = getCompoundIdFor(newSource, newTarget);
+ // If this compoundId is already taken...
+ if (existsLabel(compoundId))
+ {
+ throw new IllegalArgumentException(I18NUtil.getMessage(MSG_REF_LABEL_IN_USE, compoundId));
+ }
return persistUpdatedAssocTitle(refQName, compoundId);
}
// note: currently RMC custom assocs only
public QName updateCustomAssocDefinition(QName refQName, String newLabel)
{
- return persistUpdatedAssocTitle(refQName, newLabel);
+ // If this label is already taken...
+ if (existsLabel(newLabel))
+ {
+ throw new IllegalArgumentException(I18NUtil.getMessage(MSG_REF_LABEL_IN_USE, newLabel));
+ }
+ return persistUpdatedAssocTitle(refQName, newLabel);
}
/**
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DeclareRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DeclareRecordAction.java
index a7b0ab9bf2..3f0d89a3d3 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DeclareRecordAction.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DeclareRecordAction.java
@@ -29,6 +29,7 @@ import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase;
+import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
@@ -77,10 +78,11 @@ public class DeclareRecordAction extends RMActionExecuterAbstractBase
// remove all owner related rights
this.ownableService.setOwner(actionedUponNodeRef, OwnableService.NO_OWNER);
- }
+ }
else
{
- throw new AlfrescoRuntimeException(buildMissingPropertiesErrorString(missingProperties));
+ logger.debug(buildMissingPropertiesErrorString(missingProperties));
+ action.setParameterValue(ActionExecuterAbstractBase.PARAM_RESULT, "missingProperties");
}
}
}
@@ -95,9 +97,10 @@ public class DeclareRecordAction extends RMActionExecuterAbstractBase
StringBuilder builder = new StringBuilder(255);
builder.append(I18NUtil.getMessage(MSG_NO_DECLARE_MAND_PROP));
builder.append(" ");
- for (String missingProperty : missingProperties)
+ for (String missingProperty : missingProperties)
{
- builder.append(missingProperty).append(", ");
+ builder.append(missingProperty)
+ .append(", ");
}
return builder.toString();
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
index 70feec88db..ed279bd596 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/audit/RecordsManagementAuditServiceImpl.java
@@ -129,6 +129,8 @@ public class RecordsManagementAuditServiceImpl
private static final String MSG_WEB_RECORD = "rm.audit.web-record";
private static final String MSG_TRAIL_FILE_FAIL = "rm.audit.trail-file-fail";
private static final String MSG_AUDIT_REPORT = "rm.audit.audit-report";
+ private static final String MSG_CREATE_DISPOSITION_SCHEDULE = "rm.audit.create-disposition-schedule";
+ private static final String MSG_UNFREEZE = "rm.audit.unfreeze";
/** Logger */
private static Log logger = LogFactory.getLog(RecordsManagementAuditServiceImpl.class);
@@ -320,6 +322,10 @@ public class RecordsManagementAuditServiceImpl
new AuditEvent("applyDigitalPhotographRecord", MSG_PHOTO_RECORD));
this.auditEvents.put("applyWebRecord",
new AuditEvent("applyWebRecord", MSG_WEB_RECORD));
+ this.auditEvents.put("createDispositionSchedule",
+ new AuditEvent("createDispositionSchedule", MSG_CREATE_DISPOSITION_SCHEDULE));
+ this.auditEvents.put("unfreeze",
+ new AuditEvent("unfreeze", MSG_UNFREEZE));
}
@Override
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java
index e0ca52355d..1d20f359fa 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/capability/RMAfterInvocationProvider.java
@@ -520,29 +520,36 @@ public class RMAfterInvocationProvider extends RMSecurityCommon
// All permission checks must pass
inclusionMask.set(i, true);
-
- int parentCheckRead = checkRead(returnedObject.getChildAssocRef(i).getParentRef());
- int childCheckRead = checkRead(returnedObject.getNodeRef(i));
- for (ConfigAttributeDefintion cad : supportedDefinitions)
+ if (nodeService.exists(returnedObject.getNodeRef(i)) == false)
{
- NodeRef testNodeRef = returnedObject.getNodeRef(i);
- int checkRead = childCheckRead;
- if (cad.parent)
- {
- testNodeRef = returnedObject.getChildAssocRef(i).getParentRef();
- checkRead = parentCheckRead;
- }
-
- if (isUnfiltered(testNodeRef))
- {
- continue;
- }
-
- if (inclusionMask.get(i) && (testNodeRef != null) && (checkRead != AccessDecisionVoter.ACCESS_GRANTED))
- {
- inclusionMask.set(i, false);
- }
+ inclusionMask.set(i, false);
+ }
+ else
+ {
+ int parentCheckRead = checkRead(returnedObject.getChildAssocRef(i).getParentRef());
+ int childCheckRead = checkRead(returnedObject.getNodeRef(i));
+
+ for (ConfigAttributeDefintion cad : supportedDefinitions)
+ {
+ NodeRef testNodeRef = returnedObject.getNodeRef(i);
+ int checkRead = childCheckRead;
+ if (cad.parent)
+ {
+ testNodeRef = returnedObject.getChildAssocRef(i).getParentRef();
+ checkRead = parentCheckRead;
+ }
+
+ if (isUnfiltered(testNodeRef))
+ {
+ continue;
+ }
+
+ if (inclusionMask.get(i) && (testNodeRef != null) && (checkRead != AccessDecisionVoter.ACCESS_GRANTED))
+ {
+ inclusionMask.set(i, false);
+ }
+ }
}
// Bug out if we are limiting by size
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/event/RecordsManagementEventService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/event/RecordsManagementEventService.java
index 5e60e5b64e..a32ff9f879 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/event/RecordsManagementEventService.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/event/RecordsManagementEventService.java
@@ -73,6 +73,14 @@ public interface RecordsManagementEventService
*/
boolean existsEvent(String eventName);
+ /**
+ * Indicates whether a particular event display label exists. Returns true if it does, false otherwise.
+ *
+ * @param eventDisplayLabel event display label
+ * @return true if event display label exists, false otherwise
+ */
+ boolean existsEventDisplayLabel(String eventDisplayLabel);
+
/**
* Add an event
*
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/event/RecordsManagementEventServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/event/RecordsManagementEventServiceImpl.java
index b5084747d7..bc83fe244b 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/event/RecordsManagementEventServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/event/RecordsManagementEventServiceImpl.java
@@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.event;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -122,6 +123,23 @@ public class RecordsManagementEventServiceImpl implements RecordsManagementEvent
return getEventMap().containsKey(eventName);
}
+ /**
+ * @see org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService#existsEventDisplayLabel(java.lang.String)
+ */
+ @SuppressWarnings("rawtypes")
+ public boolean existsEventDisplayLabel(String eventDisplayLabel)
+ {
+ for (Iterator iterator = getEventMap().values().iterator(); iterator.hasNext();)
+ {
+ RecordsManagementEvent recordsManagementEvent = (RecordsManagementEvent) iterator.next();
+ if (recordsManagementEvent.getDisplayLabel().equalsIgnoreCase(eventDisplayLabel))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* @see org.alfresco.module.org_alfresco_module_rm.event.RecordsManagementEventService#addEvent(java.lang.String, java.lang.String, java.lang.String)
*/
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementNodeFormFilter.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementNodeFormFilter.java
index 43a0d08512..420c6eccec 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementNodeFormFilter.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/forms/RecordsManagementNodeFormFilter.java
@@ -18,6 +18,7 @@
*/
package org.alfresco.module.org_alfresco_module_rm.forms;
+import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -263,20 +264,31 @@ public class RecordsManagementNodeFormFilter extends RecordsManagementFormFilter
List fieldDefs = form.getFieldDefinitions();
for (FieldDefinition fieldDef : fieldDefs)
{
- if (fieldDef.getName().equals("cm:title") ||
- fieldDef.getName().equals("cm:author") ||
- fieldDef.getName().equals("rma:originator") ||
- fieldDef.getName().equals("rma:publicationDate") ||
- fieldDef.getName().equals("rma:dateReceived") ||
- fieldDef.getName().equals("rma:address") ||
- fieldDef.getName().equals("rma:otherAddress"))
- {
- fieldDef.setProtectedField(true);
+ String prefixName = fieldDef.getName();
+
+ // check the value of the property, if empty then do not mark property
+ // as read only
+ QName qname = QName.createQName(prefixName, namespaceService);
+ Serializable value = nodeService.getProperty(nodeRef, qname);
+ if (value != null)
+ {
+ if (prefixName.equals("cm:title") ||
+ prefixName.equals("cm:author") ||
+ prefixName.equals("rma:originator") ||
+ prefixName.equals("rma:publicationDate") ||
+ prefixName.equals("rma:dateReceived") ||
+ prefixName.equals("rma:address") ||
+ prefixName.equals("rma:otherAddress"))
+ {
+ fieldDef.setProtectedField(true);
+ }
}
}
- if (logger.isDebugEnabled())
+ if (logger.isDebugEnabled() == true)
+ {
logger.debug("Set email related fields to be protected");
+ }
}
/**
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJobExecuter.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJobExecuter.java
index 5aa7d4b80a..ae36e7df58 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJobExecuter.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJobExecuter.java
@@ -19,23 +19,21 @@
package org.alfresco.module.org_alfresco_module_rm.job;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
+import org.alfresco.repo.admin.RepositoryState;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
-import org.springframework.context.ApplicationEvent;
-import org.springframework.extensions.surf.util.AbstractLifecycleBean;
/**
* Records management job executer base class.
*
* @author Roy Wetherall
*/
-public abstract class RecordsManagementJobExecuter extends AbstractLifecycleBean
- implements RecordsManagementModel
+public abstract class RecordsManagementJobExecuter implements RecordsManagementModel
{
/** Retrying transaction helper */
protected RetryingTransactionHelper retryingTransactionHelper;
- /** Indicates whether the application bootstrap is complete or not */
- protected boolean bootstrapComplete = false;
+ /** Repository state helper */
+ protected RepositoryState repositoryState;
/**
* @param retryingTransactionHelper retrying transaction helper
@@ -45,13 +43,21 @@ public abstract class RecordsManagementJobExecuter extends AbstractLifecycleBea
this.retryingTransactionHelper = retryingTransactionHelper;
}
+ /**
+ * @param repositoryState repository state helper component
+ */
+ public void setRepositoryState(RepositoryState repositoryState)
+ {
+ this.repositoryState = repositoryState;
+ }
+
/**
* Executes the jobs work.
*/
public void execute()
{
// jobs not allowed to execute unless bootstrap is complete
- if (bootstrapComplete == true)
+ if (repositoryState.isBootstrapping() == false)
{
executeImpl();
}
@@ -61,32 +67,4 @@ public abstract class RecordsManagementJobExecuter extends AbstractLifecycleBea
* Jobs work implementation.
*/
public abstract void executeImpl();
-
- /**
- * @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
- */
- @Override
- protected void onBootstrap(ApplicationEvent arg0)
- {
- // record that the bootstrap has complete
- bootstrapComplete = true;
- }
-
- /**
- * @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent)
- */
- @Override
- protected void onShutdown(ApplicationEvent arg0)
- {
- // no implementation
- }
-
- /**
- * @see org.springframework.extensions.surf.util.AbstractLifecycleBean#onApplicationEvent(org.springframework.context.ApplicationEvent)
- */
- @Override
- public void onApplicationEvent(ApplicationEvent arg0)
- {
- // no implementation
- }
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementSearchBehaviour.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementSearchBehaviour.java
index ea6e0ef6ca..79823d13a7 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementSearchBehaviour.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementSearchBehaviour.java
@@ -498,15 +498,16 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel
{
if (nodeService.exists(nodeRef) == true)
{
- // Initialise the search parameteres as required
+ // Initialise the search parameters as required
setVitalRecordDefintionDetails(nodeRef);
}
}
public void vitalRecordDefintionAddAspect(NodeRef nodeRef, QName aspectTypeQName)
{
- // Only care about record folders
- if (recordsManagementService.isRecordFolder(nodeRef) == true)
+ // Only care about record folders or record categories
+ if (recordsManagementService.isRecordFolder(nodeRef) == true ||
+ recordsManagementService.isRecordCategory(nodeRef) == true)
{
updateVitalRecordDefinitionValues(nodeRef);
}
@@ -514,8 +515,9 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel
public void vitalRecordDefintionUpdateProperties(NodeRef nodeRef, Map before, Map after)
{
- // Only care about record folders
- if (recordsManagementService.isRecordFolder(nodeRef) == true)
+ // Only care about record folders or record categories
+ if (recordsManagementService.isRecordFolder(nodeRef) == true ||
+ recordsManagementService.isRecordCategory(nodeRef) == true)
{
Set props = new HashSet(1);
props.add(PROP_REVIEW_PERIOD);
@@ -535,14 +537,17 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel
applySearchAspect(nodeRef);
setVitalRecordDefintionDetails(nodeRef);
- List records = recordsManagementService.getRecords(nodeRef);
- for (NodeRef record : records)
- {
- // Apply the search aspect
- applySearchAspect(record);
-
- // Set the vital record definition details
- setVitalRecordDefintionDetails(record);
+ if (recordsManagementService.isRecordFolder(nodeRef) == true)
+ {
+ List records = recordsManagementService.getRecords(nodeRef);
+ for (NodeRef record : records)
+ {
+ // Apply the search aspect
+ applySearchAspect(record);
+
+ // Set the vital record definition details
+ setVitalRecordDefintionDetails(record);
+ }
}
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/notification/RecordsManagementNotificationHelper.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/notification/RecordsManagementNotificationHelper.java
index adb703d1a2..0f03ea0721 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/notification/RecordsManagementNotificationHelper.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/notification/RecordsManagementNotificationHelper.java
@@ -28,13 +28,16 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService;
import org.alfresco.module.org_alfresco_module_rm.security.Role;
-import org.alfresco.repo.model.Repository;
import org.alfresco.repo.notification.EMailNotificationProvider;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
+import org.alfresco.repo.tenant.TenantAdminService;
+import org.alfresco.repo.tenant.TenantUtil;
+import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
import org.alfresco.service.cmr.notification.NotificationContext;
import org.alfresco.service.cmr.notification.NotificationService;
import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthorityService;
@@ -68,11 +71,12 @@ public class RecordsManagementNotificationHelper
private NotificationService notificationService;
private RecordsManagementService recordsManagementService;
private RecordsManagementSecurityService securityService;
- private Repository repositoryHelper;
private SearchService searchService;
private NamespaceService namespaceService;
private SiteService siteService;
private AuthorityService authorityService;
+ private TenantAdminService tenantAdminService;
+ private NodeService nodeService;
/** Notification role */
private String notificationRole;
@@ -113,15 +117,6 @@ public class RecordsManagementNotificationHelper
this.notificationRole = notificationRole;
}
- /**
- *
- * @param repositoryHelper repository helper
- */
- public void setRepositoryHelper(Repository repositoryHelper)
- {
- this.repositoryHelper = repositoryHelper;
- }
-
/**
* @param searchService search service
*/
@@ -154,6 +149,22 @@ public class RecordsManagementNotificationHelper
this.authorityService = authorityService;
}
+ /**
+ * @param nodeService node service
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * @param tenantAdminService tenant admin service
+ */
+ public void setTenantAdminService(TenantAdminService tenantAdminService)
+ {
+ this.tenantAdminService = tenantAdminService;
+ }
+
/**
* @return superseded email template
*/
@@ -171,7 +182,7 @@ public class RecordsManagementNotificationHelper
{
List nodeRefs =
searchService.selectNodes(
- repositoryHelper.getRootHome(),
+ getRootNode(),
"app:company_home/app:dictionary/cm:records_management/cm:records_management_email_templates/cm:notify-records-due-for-review-email.ftl", null,
namespaceService,
false);
@@ -183,6 +194,23 @@ public class RecordsManagementNotificationHelper
return dueForReviewTemplate;
}
+ /**
+ * Helper method to get root node in a tenant safe way.
+ *
+ * @return NodeRef root node of spaces store
+ */
+ private NodeRef getRootNode()
+ {
+ String tenantDomain = tenantAdminService.getCurrentUserDomain();
+ return TenantUtil.runAsSystemTenant(new TenantRunAsWork()
+ {
+ public NodeRef doWork() throws Exception
+ {
+ return nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
+ }
+ }, tenantDomain);
+ }
+
/**
* Sends records due for review email notification.
*
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomRefDelete.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomRefDelete.java
index bc84bb82ce..2d2e5f57e5 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomRefDelete.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomRefDelete.java
@@ -104,6 +104,7 @@ public class CustomRefDelete extends AbstractRmWebScript
}
rmAdminService.removeCustomReference(fromNodeRef, toNodeRef, qn);
+ rmAdminService.removeCustomReference(toNodeRef, fromNodeRef, qn);
result.put("success", true);
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomReferenceDefinitionPost.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomReferenceDefinitionPost.java
index efe3492ab1..854ab8676b 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomReferenceDefinitionPost.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomReferenceDefinitionPost.java
@@ -85,6 +85,11 @@ public class CustomReferenceDefinitionPost extends AbstractRmWebScript
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"Could not parse JSON from req.", je);
}
+ catch (IllegalArgumentException iae)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST,
+ iae.getMessage(), iae);
+ }
return ftlModel;
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomReferenceDefinitionPut.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomReferenceDefinitionPut.java
index 02186dde62..3abc94d457 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomReferenceDefinitionPut.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/CustomReferenceDefinitionPut.java
@@ -86,6 +86,11 @@ public class CustomReferenceDefinitionPut extends AbstractRmWebScript
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"Could not parse JSON from req.", je);
}
+ catch (IllegalArgumentException iae)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST,
+ iae.getMessage(), iae);
+ }
return ftlModel;
}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionLifecycleGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionLifecycleGet.java
index f6dfe3b76e..e7d48938ca 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionLifecycleGet.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/DispositionLifecycleGet.java
@@ -23,8 +23,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.servlet.http.HttpServletResponse;
-
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionAction;
import org.alfresco.module.org_alfresco_module_rm.event.EventCompletionDetails;
@@ -68,9 +66,12 @@ public class DispositionLifecycleGet extends DispositionAbstractBase
DispositionAction nextAction = this.dispositionService.getNextDispositionAction(nodeRef);
if (nextAction == null)
{
- status.setCode(HttpServletResponse.SC_NOT_FOUND,
- "Node " + nodeRef.toString() + " does not have a disposition lifecycle");
- return null;
+ Map nextActionModel = new HashMap(2);
+ nextActionModel.put("notFound", true);
+ nextActionModel.put("message", "Node " + nodeRef.toString() + " does not have a disposition lifecycle");
+ Map model = new HashMap(1);
+ model.put("nextaction", nextActionModel);
+ return model;
}
else
{
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/EmailMapPost.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/EmailMapPost.java
index a712cc2e64..369f069218 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/EmailMapPost.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/EmailMapPost.java
@@ -53,6 +53,16 @@ public class EmailMapPost extends DeclarativeWebScript
JSONObject json = null;
json = new JSONObject(new JSONTokener(req.getContent().getContent()));
+ if(json.has("delete"))
+ {
+ JSONArray toDelete = json.getJSONArray("delete");
+ for(int i = 0 ; i < toDelete.length(); i++)
+ {
+ JSONObject val = toDelete.getJSONObject(i);
+ customEmailMappingService.deleteCustomMapping(val.getString("from"), val.getString("to"));
+ }
+ }
+
if(json.has("add"))
{
JSONArray toAdd = json.getJSONArray("add");
@@ -64,17 +74,6 @@ public class EmailMapPost extends DeclarativeWebScript
}
}
- if(json.has("delete"))
- {
- JSONArray toDelete = json.getJSONArray("delete");
- for(int i = 0 ; i < toDelete.length(); i++)
- {
- JSONObject val = toDelete.getJSONObject(i);
- customEmailMappingService.deleteCustomMapping(val.getString("from"), val.getString("to"));
- }
- }
-
-
// Set the return value.
Set emailMap = customEmailMappingService.getCustomMappings();
// create model object with the lists model
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/RmActionPost.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/RmActionPost.java
index 616410a690..3c16f5d5d7 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/RmActionPost.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/RmActionPost.java
@@ -50,175 +50,173 @@ import org.json.JSONTokener;
*/
public class RmActionPost extends DeclarativeWebScript
{
- private static Log logger = LogFactory.getLog(RmActionPost.class);
-
- private static final String PARAM_NAME = "name";
- private static final String PARAM_NODE_REF = "nodeRef";
- private static final String PARAM_NODE_REFS = "nodeRefs";
- private static final String PARAM_PARAMS = "params";
-
- private NodeService nodeService;
- private RecordsManagementActionService rmActionService;
-
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
+ private static Log logger = LogFactory.getLog(RmActionPost.class);
- public void setRecordsManagementActionService(RecordsManagementActionService rmActionService)
- {
- this.rmActionService = rmActionService;
- }
+ private static final String PARAM_NAME = "name";
+ private static final String PARAM_NODE_REF = "nodeRef";
+ private static final String PARAM_NODE_REFS = "nodeRefs";
+ private static final String PARAM_PARAMS = "params";
- @SuppressWarnings("unchecked")
- @Override
- public Map executeImpl(WebScriptRequest req, Status status, Cache cache)
- {
- String reqContentAsString;
- try
- {
- reqContentAsString = req.getContent().getContent();
- }
- catch (IOException iox)
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST,
- "Could not read content from req.", iox);
- }
+ private NodeService nodeService;
+ private RecordsManagementActionService rmActionService;
- String actionName = null;
- List targetNodeRefs = null;
- Map actionParams = new HashMap(3);
-
- try
- {
- JSONObject jsonObj = new JSONObject(new JSONTokener(reqContentAsString));
-
- // Get the action name
- if (jsonObj.has(PARAM_NAME) == true)
- {
- actionName = jsonObj.getString(PARAM_NAME);
- }
-
- // Get the target references
- if (jsonObj.has(PARAM_NODE_REF) == true)
- {
- NodeRef nodeRef = new NodeRef(jsonObj.getString(PARAM_NODE_REF));
- targetNodeRefs = new ArrayList(1);
- targetNodeRefs.add(nodeRef);
- }
- if (jsonObj.has(PARAM_NODE_REFS) == true)
- {
- JSONArray jsonArray = jsonObj.getJSONArray(PARAM_NODE_REFS);
- if (jsonArray.length() != 0)
- {
- targetNodeRefs = new ArrayList(jsonArray.length());
- for (int i = 0; i < jsonArray.length(); i++)
- {
- NodeRef nodeRef = new NodeRef(jsonArray.getString(i));
- targetNodeRefs.add(nodeRef);
- }
- }
- }
-
- // params are optional.
- if (jsonObj.has(PARAM_PARAMS))
- {
- JSONObject paramsObj = jsonObj.getJSONObject(PARAM_PARAMS);
- for (Iterator iter = paramsObj.keys(); iter.hasNext(); )
- {
- Object nextKey = iter.next();
- String nextKeyString = (String)nextKey;
- Object nextValue = paramsObj.get(nextKeyString);
-
- // Check for date values
- if (nextValue instanceof JSONObject)
- {
- if (((JSONObject)nextValue).has("iso8601") == true)
- {
- String dateStringValue = ((JSONObject)nextValue).getString("iso8601");
- nextValue = ISO8601DateFormat.parse(dateStringValue);
- }
- }
-
- actionParams.put(nextKeyString, (Serializable)nextValue);
- }
- }
- }
- catch (JSONException exception)
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Unable to parse request JSON.");
- }
-
- // validate input: check for mandatory params.
- // Some RM actions can be posted without a nodeRef.
- if (actionName == null)
- {
- throw new WebScriptException(Status.STATUS_BAD_REQUEST,
- "A mandatory parameter has not been provided in URL");
- }
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
- // Check that all the nodes provided exist and build report string
- StringBuffer targetNodeRefsString = new StringBuffer(30);
- boolean firstTime = true;
- for (NodeRef targetNodeRef : targetNodeRefs)
- {
- if (nodeService.exists(targetNodeRef) == false)
- {
- throw new WebScriptException(Status.STATUS_NOT_FOUND,
- "The targetNode does not exist (" + targetNodeRef.toString() + ")");
- }
-
- // Build the string
- if (firstTime == true)
- {
- firstTime = false;
- }
- else
- {
- targetNodeRefsString.append(", ");
- }
- targetNodeRefsString.append(targetNodeRef.toString());
- }
+ public void setRecordsManagementActionService(RecordsManagementActionService rmActionService)
+ {
+ this.rmActionService = rmActionService;
+ }
- // Proceed to execute the specified action on the specified node.
- if (logger.isDebugEnabled())
- {
- StringBuilder msg = new StringBuilder();
- msg.append("Executing Record Action ")
- .append(actionName)
- .append(", (")
- .append(targetNodeRefsString.toString())
- .append("), ")
- .append(actionParams);
- logger.debug(msg.toString());
- }
-
- Map model = new HashMap();
- if (targetNodeRefs.isEmpty())
- {
- RecordsManagementActionResult result = this.rmActionService.executeRecordsManagementAction(actionName, actionParams);
- if (result.getValue() != null)
- {
- model.put("result", result.getValue().toString());
- }
- }
- else
- {
- Map resultMap = this.rmActionService.executeRecordsManagementAction(targetNodeRefs, actionName, actionParams);
- Map results = new HashMap(resultMap.size());
- for (NodeRef nodeRef : resultMap.keySet())
- {
- Object value = resultMap.get(nodeRef).getValue();
- if (value != null)
- {
- results.put(nodeRef.toString(), resultMap.get(nodeRef).getValue().toString());
- }
- }
- model.put("results", results);
- }
-
- model.put("message", "Successfully queued action [" + actionName + "] on " + targetNodeRefsString.toString());
+ @SuppressWarnings("unchecked")
+ @Override
+ public Map executeImpl(WebScriptRequest req, Status status, Cache cache)
+ {
+ String reqContentAsString;
+ try
+ {
+ reqContentAsString = req.getContent().getContent();
+ }
+ catch (IOException iox)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST,
+ "Could not read content from req.", iox);
+ }
- return model;
- }
+ String actionName = null;
+ List targetNodeRefs = new ArrayList(1);
+ Map actionParams = new HashMap(3);
+
+ try
+ {
+ JSONObject jsonObj = new JSONObject(new JSONTokener(reqContentAsString));
+
+ // Get the action name
+ if (jsonObj.has(PARAM_NAME) == true)
+ {
+ actionName = jsonObj.getString(PARAM_NAME);
+ }
+
+ // Get the target references
+ if (jsonObj.has(PARAM_NODE_REF) == true)
+ {
+ NodeRef nodeRef = new NodeRef(jsonObj.getString(PARAM_NODE_REF));
+ targetNodeRefs.add(nodeRef);
+ }
+ if (jsonObj.has(PARAM_NODE_REFS) == true)
+ {
+ JSONArray jsonArray = jsonObj.getJSONArray(PARAM_NODE_REFS);
+ if (jsonArray.length() != 0)
+ {
+ targetNodeRefs = new ArrayList(jsonArray.length());
+ for (int i = 0; i < jsonArray.length(); i++)
+ {
+ NodeRef nodeRef = new NodeRef(jsonArray.getString(i));
+ targetNodeRefs.add(nodeRef);
+ }
+ }
+ }
+
+ // params are optional.
+ if (jsonObj.has(PARAM_PARAMS))
+ {
+ JSONObject paramsObj = jsonObj.getJSONObject(PARAM_PARAMS);
+ for (Iterator iter = paramsObj.keys(); iter.hasNext(); )
+ {
+ String nextKeyString = iter.next();
+ Object nextValue = paramsObj.get(nextKeyString);
+
+ // Check for date values
+ if (nextValue instanceof JSONObject)
+ {
+ if (((JSONObject)nextValue).has("iso8601") == true)
+ {
+ String dateStringValue = ((JSONObject)nextValue).getString("iso8601");
+ nextValue = ISO8601DateFormat.parse(dateStringValue);
+ }
+ }
+
+ actionParams.put(nextKeyString, (Serializable)nextValue);
+ }
+ }
+ }
+ catch (JSONException exception)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Unable to parse request JSON.");
+ }
+
+ // validate input: check for mandatory params.
+ // Some RM actions can be posted without a nodeRef.
+ if (actionName == null)
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST,
+ "A mandatory parameter has not been provided in URL");
+ }
+
+ // Check that all the nodes provided exist and build report string
+ StringBuffer targetNodeRefsString = new StringBuffer(30);
+ boolean firstTime = true;
+ for (NodeRef targetNodeRef : targetNodeRefs)
+ {
+ if (nodeService.exists(targetNodeRef) == false)
+ {
+ throw new WebScriptException(Status.STATUS_NOT_FOUND,
+ "The targetNode does not exist (" + targetNodeRef.toString() + ")");
+ }
+
+ // Build the string
+ if (firstTime == true)
+ {
+ firstTime = false;
+ }
+ else
+ {
+ targetNodeRefsString.append(", ");
+ }
+ targetNodeRefsString.append(targetNodeRef.toString());
+ }
+
+ // Proceed to execute the specified action on the specified node.
+ if (logger.isDebugEnabled())
+ {
+ StringBuilder msg = new StringBuilder();
+ msg.append("Executing Record Action ")
+ .append(actionName)
+ .append(", (")
+ .append(targetNodeRefsString.toString())
+ .append("), ")
+ .append(actionParams);
+ logger.debug(msg.toString());
+ }
+
+ Map model = new HashMap();
+ if (targetNodeRefs.isEmpty())
+ {
+ RecordsManagementActionResult result = this.rmActionService.executeRecordsManagementAction(actionName, actionParams);
+ if (result.getValue() != null)
+ {
+ model.put("result", result.getValue().toString());
+ }
+ }
+ else
+ {
+ Map resultMap = this.rmActionService.executeRecordsManagementAction(targetNodeRefs, actionName, actionParams);
+ Map results = new HashMap(resultMap.size());
+ for (NodeRef nodeRef : resultMap.keySet())
+ {
+ Object value = resultMap.get(nodeRef).getValue();
+ if (value != null)
+ {
+ results.put(nodeRef.toString(), resultMap.get(nodeRef).getValue().toString());
+ }
+ }
+ model.put("results", results);
+ }
+
+ model.put("message", "Successfully queued action [" + actionName + "] on " + targetNodeRefsString.toString());
+
+ return model;
+ }
}
\ No newline at end of file
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmEventPut.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmEventPut.java
index 8717870eea..1af46bd6e6 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmEventPut.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmEventPut.java
@@ -90,6 +90,12 @@ public class RmEventPut extends DeclarativeWebScript
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "No event display label provided.");
}
+ if (rmEventService.existsEventDisplayLabel(eventDisplayLabel))
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST,
+ "Cannot edit event. The event display label '"
+ + eventDisplayLabel + "' already exists.");
+ }
String eventType = null;
if (json.has("eventType") == true)
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmEventsPost.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmEventsPost.java
index 02aad56389..5384764881 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmEventsPost.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/admin/RmEventsPost.java
@@ -90,6 +90,12 @@ public class RmEventsPost extends DeclarativeWebScript
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "No event display label provided.");
}
+ if (rmEventService.existsEventDisplayLabel(eventDisplayLabel))
+ {
+ throw new WebScriptException(Status.STATUS_BAD_REQUEST,
+ "Cannot create event. The event display label '"
+ + eventDisplayLabel + "' already exists.");
+ }
String eventType = null;
if (json.has("eventType") == true)
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java
index a1d9ba4459..df8c40bc25 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/RMSearchGet.java
@@ -282,12 +282,12 @@ public class RMSearchGet extends DeclarativeWebScript
relPath.append(getName());
try
{
- this.browseUrl = "documentlibrary?path=" + URLEncoder.encode(relPath.toString(), "UTF-8");
+ this.browseUrl = "documentlibrary?path=" + URLEncoder.encode(relPath.toString(), "UTF-8").replaceAll("\\+","%20");
}
catch (UnsupportedEncodingException e)
{
throw new AlfrescoRuntimeException("Could not process search results.", e);
- }
+ }
}
}
else
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/forms/RMMetaDataGet.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/forms/RMMetaDataGet.java
index b29d88afc8..1d3345ad88 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/forms/RMMetaDataGet.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/script/slingshot/forms/RMMetaDataGet.java
@@ -53,6 +53,9 @@ public class RMMetaDataGet extends DeclarativeWebScript
/** NodeRef pattern */
private static final Pattern nodeRefPattern = Pattern.compile(".+://.+/.+");
+ /** QName pattern */
+ private static final Pattern qnamePattern = Pattern.compile(".+:[^=,]+");
+
/** Records management service */
private RecordsManagementService rmService;
@@ -103,14 +106,18 @@ public class RMMetaDataGet extends DeclarativeWebScript
if (nodeRef == null || nodeRef.length() == 0)
{
String type = req.getParameter(PARAM_TYPE);
- if (type != null && type.length() != 0)
+ if (type != null && type.length() != 0 && type.indexOf(':') != -1)
{
- QName qname = QName.createQName(type, namespaceService);
- FilePlanComponentKind kind = rmService.getFilePlanComponentKindFromType(qname);
- if (kind != null)
- {
- result = kind.toString();
- }
+ Matcher m = qnamePattern.matcher(type);
+ if (m.matches() == true)
+ {
+ QName qname = QName.createQName(type, namespaceService);
+ FilePlanComponentKind kind = rmService.getFilePlanComponentKindFromType(qname);
+ if (kind != null)
+ {
+ result = kind.toString();
+ }
+ }
}
}
else
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java
index a397570951..7a625d870b 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java
@@ -332,7 +332,48 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe
*/
public void onCreateRMContainer(ChildAssociationRef childAssocRef)
{
- setUpPermissions(childAssocRef.getChildRef());
+ final NodeRef recordCategory = childAssocRef.getChildRef();
+ setUpPermissions(recordCategory);
+
+ // Pull any permissions found on the parent (ie the record category)
+ final NodeRef parentNodeRef = childAssocRef.getParentRef();
+ if (parentNodeRef != null && nodeService.exists(parentNodeRef) == true)
+ {
+ AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork