RM-1211: Generate hold report

* FileHoldReport capability added (and patched)
 * hold report type added to report model
 * hold template added, bootstraped (and patched)
 * UI action to file hold report added and sensitive to capability
 * report actions refactored into a single, general purpose, file report action (can be exposed as rule in future)
 * refactoring and extending of report generators (including declarative report generator)
 * unit test for file report action
 * integration test for hold report generation
 * added Sprin custom property editor registrar and registered QName property editor, this allows short name string forms of
   QNames to be specified and converted to QName from bean definitions (perhaps something useful for core)



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@68235 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-04-29 07:21:54 +00:00
parent 706dc33384
commit fde0de1010
53 changed files with 1575 additions and 428 deletions

View File

@@ -227,6 +227,23 @@
</view:properties>
</cm:content>
</cm:contains>
<cm:contains>
<cm:content view:childName="cm:report_rmr_holdReport.html.ftl">
<view:aspects>
<cm:titled></cm:titled>
<cm:author></cm:author>
</view:aspects>
<view:properties>
<sys:store-protocol>workspace</sys:store-protocol>
<sys:store-identifier>SpacesStore</sys:store-identifier>
<sys:node-uuid>rmr_holdReport</sys:node-uuid>
<cm:description>Hold report template.</cm:description>
<cm:content>contentUrl=classpath:alfresco/module/org_alfresco_module_rm/bootstrap/report/report_rmr_holdReport.html.ftl|mimetype=text/plain|encoding=UTF-8</cm:content>
<cm:title>Hold Report Template</cm:title>
<cm:name>report_rmr_holdReport.html.ftl</cm:name>
</view:properties>
</cm:content>
</cm:contains>
</view:associations>
</cm:folder>
</cm:contains>

View File

@@ -0,0 +1,112 @@
<html>
<head>
<style type="text/css"><!--
body
{
font-family: Arial, sans-serif;
font-size: 14px;
color: #4c4c4c;
}
a, a:visited
{
color: #0072cf;
}
--></style>
</head>
<body bgcolor="#dddddd">
<table width="100%" cellpadding="20" cellspacing="0" border="0" bgcolor="#dddddd">
<tr>
<td width="100%" align="center">
<table width="70%" cellpadding="0" cellspacing="0" bgcolor="white" style="background-color: white; border: 1px solid #aaaaaa;">
<tr>
<td width="100%">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="padding: 10px 30px 0px;">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<img src="${shareUrl}/res/components/images/task-64.png" alt="" width="64" height="64" border="0" style="padding-right: 20px;" />
</td>
<td>
<div style="font-size: 22px; padding-bottom: 4px;">
${message("file.report.hold.report")}
</div>
</td>
</tr>
</table>
<div style="font-size: 14px; margin: 12px 0px 24px 0px; padding-top: 10px; border-top: 1px solid #aaaaaa;">
<table cellpadding="2" cellspacing="3" border="0">
<tr>
<td><i>${message("file.report.hold.name")}:</i></td>
<td>${node.properties["cm:name"]}</td>
</tr>
<tr>
<td><i>${message("file.report.hold.description")}:</i></td>
<td>
<#if node.properties["cm:description"]??>
${node.properties["cm:description"]}
</#if>
</td>
</tr>
<tr>
<td><i>${message("file.report.hold.reason")}:</i></td>
<td>${node.properties["rma:holdReason"]}</td>
</tr>
</table>
<#if node.childAssociations["rma:frozenRecords"]??>
<div style="font-size: 14px; margin: 12px 0px 24px 0px; padding-top: 10px; border-top: 1px solid #aaaaaa;">
<table cellpadding="2" cellspacing="3" border="0">
<tr>
<td><i>${message("file.report.hold.held")}:</i></td>
<td></td>
</tr>
</table>
<table cellpadding="0" callspacing="0" border="0" bgcolor="#eeeeee" style="padding:10px; border: 1px solid #aaaaaa;">
<tr>
<td>
<table cellpadding="0" cellspacing="0" border="0">
<#list node.childAssociations["rma:frozenRecords"] as child>
<tr>
<td valign="top">
<img src="${url}/${child.icon32}" alt="" width="32" height="32" border="0" style="padding-right: 10px;" />
</td>
<td>
<table cellpadding="2" cellspacing="0" border="0">
<tr>
<td>${child.properties["rma:identifier"]} <b>${child.properties.name}</b></td>
</tr>
</table>
</td>
</tr>
</#list>
</table>
</td>
</tr>
</table>
</#if>
<div style="font-size: 14px; margin: 12px 0px 24px 0px; padding-top: 10px; border-top: 1px solid #aaaaaa;">
</div>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style="padding: 10px 30px;">
<img src="${shareUrl}/themes/default/images/app-logo.png" alt="" width="117" height="48" border="0" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -58,6 +58,7 @@
</div>
</body>
</html>
<#macro generateTransferFolderHTML transferNode>
<span class="nodeName">
${transferNode.properties["name"]?html}
@@ -69,6 +70,7 @@
</#list>
</div>
</#macro>
<#macro generateTransferRecordHTML transferNode>
<div class="record">
<span class="nodeName">

View File

@@ -113,4 +113,23 @@
<property name="group"><ref bean="holdControlsGroup"/></property>
<property name="index" value="60" />
</bean>
<!-- file hold report capability -->
<bean id="rmFileHoldReportCapability"
parent="declarativeCapability">
<property name="name" value="FileHoldReport" />
<property name="permission" value="FileHoldReport" /> <!-- Associated permission -->
<property name="kinds">
<list>
<value>HOLD</value> <!-- Only applies to holds -->
</list>
</property>
<property name="conditions">
<map>
<entry key="capabilityCondition.filling" value="true"/> <!-- Must have read and file permissions -->
</map>
</property>
<property name="group"><ref bean="holdControlsGroup"/></property> <!-- Part of the hold group of capabilities -->
<property name="index" value="80" />
</bean>
</beans>

View File

@@ -175,12 +175,9 @@ retain.description=Retain
# Add Record Types
addRecordTypes.title=Add record types
addRecordTypes.description=Adds the selected type(s) to the record
# Destruction report
destructionReport.title=Destruction report
destructionReport.description=Destruction report
# Transfer Report
transferReport.title=Transfer Report
transferReport.description=Transfer Report
# File report
fileReport.title=File report
fileReport.description=File report
# Action parameter constraints
rm-ac-is-kind-kinds.record_category=Record Category

View File

@@ -65,6 +65,7 @@ capability.ViewUpdateReasonsForFreeze.title=View Update Reasons for Freeze
capability.CreateHold.title=Create Hold
capability.AddToHold.title=Add to Hold
capability.RemoveFromHold.title=Remove from Hold
capability.FileHoldReport=File Hold Report
# Audit
capability.group.audit.title=Audit

View File

@@ -1,7 +1,13 @@
rmr_recordsmanagementreport.description=Records Management Report Content Model
rmr_recordsmanagementreport.type.rmr_report.title=Records Management Report
rmr_recordsmanagementreport.type.rmr_report.title=Report
rmr_recordsmanagementreport.type.rmr_report.description=Records management report.
rmr_recordsmanagementreport.type.rmr_destructionReport.title=Records Management Report
rmr_recordsmanagementreport.type.rmr_destructionReport.description=Records management destruction report.
rmr_recordsmanagementreport.type.rmr_destructionReport.title=Transfer Report
rmr_recordsmanagementreport.type.rmr_destructionReport.description=Records management transfer report.
rmr_recordsmanagementreport.type.rmr_destructionReport.title=Destruction Report
rmr_recordsmanagementreport.type.rmr_destructionReport.description=Records management destruction report.
rmr_recordsmanagementreport.type.rmr_holdReport.title=Hold Report
rmr_recordsmanagementreport.type.rmr_holdReport.description=Records management hold report.

View File

@@ -1,2 +1 @@
report.rmr_destructionReport.name=Destruction Report (${node.rma:identifier} ${node.cm:name}).html
report.rmr_transferReport.name=Transfer Report (${node.rma:identifier} ${node.cm:name}).html
report.default=Report

View File

@@ -1,2 +1,2 @@
report.rmr_destructionReport.name=Bericht \u00fcber vernichtete Datens\u00e4tze (${node.rma:identifier} ${node.cm:name}).html
report.rmr_destructionReport.name=Bericht \u00fcber vernichtete Datens\u00e4tze (${node.rma:identifier} ${node.cm:name})

View File

@@ -1,2 +1,2 @@
report.rmr_destructionReport.name=Informe de destrucci\u00f3n (${node.rma:identifier} ${node.cm:name}).html
report.rmr_destructionReport.name=Informe de destrucci\u00f3n (${node.rma:identifier} ${node.cm:name})

View File

@@ -1,2 +1,2 @@
report.rmr_destructionReport.name=Rapport de destruction (${node.rma:identifier} ${node.cm:name}).html
report.rmr_destructionReport.name=Rapport de destruction (${node.rma:identifier} ${node.cm:name})

View File

@@ -1,2 +1,2 @@
report.rmr_destructionReport.name=Report di eliminazione permanente (${node.rma:identifier} ${node.cm:name}).html
report.rmr_destructionReport.name=Report di eliminazione permanente (${node.rma:identifier} ${node.cm:name})

View File

@@ -1,2 +1,2 @@
report.rmr_destructionReport.name=\u5ec3\u68c4\u30ec\u30dd\u30fc\u30c8(${node.rma:identifier} ${node.cm:name}).html
report.rmr_destructionReport.name=\u5ec3\u68c4\u30ec\u30dd\u30fc\u30c8(${node.rma:identifier} ${node.cm:name})

View File

@@ -1,2 +1,2 @@
report.rmr_destructionReport.name=Vernietingsrapport (${node.rma:identifier} ${node.cm:name}).html
report.rmr_destructionReport.name=Vernietingsrapport (${node.rma:identifier} ${node.cm:name})

View File

@@ -1,2 +1,2 @@
report.rmr_destructionReport.name=\u9500\u6bc1\u62a5\u544a (${node.rma:identifier} ${node.cm:name}).html
report.rmr_destructionReport.name=\u9500\u6bc1\u62a5\u544a (${node.rma:identifier} ${node.cm:name})

View File

@@ -17,4 +17,9 @@ file.report.performed.by=Performed By
file.report.record=Record
file.report.record.folder=Record Folder
file.report.unique.folder.identifier=Unique Folder Identifier
file.report.unique.record.identifier=Unique Record Identifier
file.report.unique.record.identifier=Unique Record Identifier
file.report.hold.report=Hold Report
file.report.hold.name=Hold Name
file.report.hold.description=Hold Description
file.report.hold.reason=Hold Reason
file.report.hold.held=Held

View File

@@ -92,6 +92,7 @@
<includePermissionGroup type="rma:filePlanComponent" permissionGroup="CreateHold"/>
<includePermissionGroup type="rma:filePlanComponent" permissionGroup="AddToHold"/>
<includePermissionGroup type="rma:filePlanComponent" permissionGroup="RemoveFromHold"/>
<includePermissionGroup type="rma:filePlanComponent" permissionGroup="FileHoldReport"/>
</permissionGroup>
<permissionGroup name="Filing" allowFullControl="false" expose="true">
@@ -177,6 +178,7 @@
<permissionGroup name="CreateHold" expose="false" allowFullControl="false"/>
<permissionGroup name="AddToHold" expose="false" allowFullControl="false"/>
<permissionGroup name="RemoveFromHold" expose="false" allowFullControl="false"/>
<permissionGroup name="FileHoldReport" expose="false" allowFullControl="false"/>
<!-- End -->
@@ -454,7 +456,7 @@
<grantedToGroup permissionGroup="LinkToRecords"/>
</permission>
<!-- Added since V2.1 -->
<!-- Added since V2.2 -->
<permission name="_CreateHold" expose="false">
<grantedToGroup permissionGroup="CreateHold"/>
@@ -467,6 +469,11 @@
<permission name="_RemoveFromHold" expose="false">
<grantedToGroup permissionGroup="RemoveFromHold"/>
</permission>
<permission name="_FileHoldReport" expose="false">
<grantedToGroup permissionGroup="FileHoldReport"/>
</permission>
</permissionSet>
</permissions>

View File

@@ -35,11 +35,15 @@
<parent>cm:content</parent>
</type>
<type name="rmr:destructionReport">
<title>Report</title>
<title>Destruction Report</title>
<parent>rmr:report</parent>
</type>
<type name="rmr:transferReport">
<title>Transfer</title>
<title>Transfer Report</title>
<parent>rmr:report</parent>
</type>
<type name="rmr:holdReport">
<title>Hold Report</title>
<parent>rmr:report</parent>
</type>
</types>

View File

@@ -3,6 +3,23 @@
<beans>
<!-- Custom property editors -->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<ref bean="customPropertyEditorRegistrar"/>
</list>
</property>
</bean>
<bean id="customPropertyEditorRegistrar"
class="org.alfresco.module.org_alfresco_module_rm.util.CustomPropertyEditorRegistrar">
<property name="namespaceService" ref="NamespaceService"/>
</bean>
<!-- Import extended repository context -->
<import resource="classpath:alfresco/module/org_alfresco_module_rm/extended-repository-context.xml"/>
<!-- Bootstrap records management data -->

View File

@@ -9,7 +9,7 @@
<property name="description" value="RM patch executer"/>
<property name="sinceVersion" value="2.2"/>
<property name="executeOnceOnly" value="false"/>
<property name="moduleSchema" value="1005"/>
<property name="moduleSchema" value="1007"/>
<property name="attributeService" ref="AttributeService" />
<property name="dependsOn">
<list>

View File

@@ -59,5 +59,26 @@
<value>${rm.ghosting.enabled}</value>
</property>
</bean>
<bean id="rm.holdReportPatch"
parent="rm.parentModulePatch"
class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22HoldReportPatch">
<property name="description" value="Patches the hold report template."/>
<property name="fixesToSchema" value="1005"/>
<property name="targetSchema" value="1006"/>
<property name="nodeService" ref="NodeService"/>
<property name="contentService" ref="ContentService"/>
</bean>
<bean id="rm.fileHoldReportCapabilityPatch"
parent="rm.parentModulePatch"
class="org.alfresco.module.org_alfresco_module_rm.patch.v22.RMv22FileHoldReportCapabilityPatch">
<property name="description" value="Add FileHoldReport capability."/>
<property name="fixesToSchema" value="1006"/>
<property name="targetSchema" value="1007"/>
<property name="filePlanService" ref="FilePlanService"/>
<property name="filePlanRoleService" ref="FilePlanRoleService"/>
<property name="capabilityService" ref="CapabilityService"/>
</bean>
</beans>

View File

@@ -1054,5 +1054,35 @@
<bean id="addRecordTypes" class="org.alfresco.module.org_alfresco_module_rm.action.impl.AddRecordTypeAction" parent="rmAction">
<property name="publicAction" value="true"/>
</bean>
<!-- file report action -->
<bean id="fileReport"
class="org.alfresco.module.org_alfresco_module_rm.action.impl.FileReportAction"
parent="rmAction">
<property name="reportService" ref="ReportService" />
<property name="publicAction" value="false"/>
</bean>
<bean id="fileReport_proxy" parent="rmProxyAction" >
<property name="target">
<ref bean="fileReport"/>
</property>
<property name="interceptorNames">
<list>
<idref bean="fileReport_security"/>
</list>
</property>
</bean>
<bean id="fileReport_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor" parent="actionSecurity">
<property name="objectDefinitionSource">
<value>
org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.execute=RM_ALLOW
org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.*=RM_ALLOW
org.alfresco.repo.action.executer.ActionExecuter.*=RM_ALLOW
</value>
</property>
</bean>
</beans>

View File

@@ -74,72 +74,32 @@
<property name="mimetypeService" ref="MimetypeService"/>
<property name="fileFolderService" ref="FileFolderService"/>
<property name="templateService" ref="TemplateService"/>
<property name="parameterProcessorComponent" ref="parameterProcessorComponent"/>
<property name="nodeService" ref="NodeService"/>
<property name="dictionaryService" ref="DictionaryService"/>
<property name="repository" ref="repositoryHelper" />
<property name="sysAdminParams" ref="sysAdminParams" />
</bean>
<bean id="destructionReportGenerator" parent="declarativeReportGenerator">
<property name="reportTypeName" value="rmr:destructionReport" />
<property name="reportType" value="rmr:destructionReport" />
</bean>
<bean id="transferReportGenerator" parent="declarativeReportGenerator">
<property name="reportTypeName" value="rmr:transferReport" />
</bean>
<!-- Report Actions -->
<bean id="baseReportAction" abstract="true" parent="rmAction">
<property name="reportService" ref="reportService" />
</bean>
<bean id="transferReport"
class="org.alfresco.module.org_alfresco_module_rm.report.action.TransferReportAction"
parent="baseReportAction" />
<bean id="transferReport_proxy" parent="rmProxyAction" >
<property name="target">
<ref bean="transferReport"/>
</property>
<property name="interceptorNames">
<list>
<idref bean="transferReport_security"/>
</list>
<bean id="transferReportGenerator" parent="declarativeReportGenerator" class="org.alfresco.module.org_alfresco_module_rm.report.generator.transfer.TransferReportGenerator">
<property name="dispositionService" ref="DispositionService"/>
<property name="reportType" value="rmr:transferReport" />
<property name="applicableTypes">
<set>
<value>rma:transfer</value>
</set>
</property>
</bean>
<bean id="transferReport_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor" parent="actionSecurity">
<property name="objectDefinitionSource">
<value>
org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.execute=RM_CAP.0.rma:filePlanComponent.FileTransferReport
org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.*=RM_ALLOW
org.alfresco.repo.action.executer.ActionExecuter.*=RM_ALLOW
</value>
</property>
</bean>
<bean id="destructionReport"
class="org.alfresco.module.org_alfresco_module_rm.report.action.DestructionReportAction"
parent="baseReportAction" />
<bean id="destructionReport_proxy" parent="rmProxyAction" >
<property name="target">
<ref bean="destructionReport"/>
</property>
<property name="interceptorNames">
<list>
<idref bean="destructionReport_security"/>
</list>
</property>
</bean>
<bean id="destructionReport_security" class="org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityInterceptor" parent="actionSecurity">
<property name="objectDefinitionSource">
<value>
org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.execute=RM_CAP.0.rma:filePlanComponent.FileDestructionReport
org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction.*=RM_ALLOW
org.alfresco.repo.action.executer.ActionExecuter.*=RM_ALLOW
</value>
<bean id="holdReportGenerator" parent="declarativeReportGenerator">
<property name="reportType" value="rmr:holdReport" />
<property name="applicableTypes">
<set>
<value>rma:hold</value>
</set>
</property>
</bean>

View File

@@ -868,4 +868,15 @@
</property>
<property name="capability" value ="RemoveFromHold"/>
</bean>
<bean id="jsonConversionComponent.fileHoldReport"
parent="jsonConversionComponent.baseAction">
<property name="name" value="fileHoldReport"/>
<property name="kinds">
<set>
<value>HOLD</value>
</set>
</property>
<property name="capability" value ="FileHoldReport"/>
</bean>
</beans>

View File

@@ -141,7 +141,8 @@
"FileTransferReport",
"CreateHold",
"AddToHold",
"RemoveFromHold"
"RemoveFromHold",
"FileHoldReport"
]
},
{
@@ -211,7 +212,8 @@
"FileTransferReport",
"CreateHold",
"AddToHold",
"RemoveFromHold"
"RemoveFromHold",
"FileHoldReport"
]
}
]

View File

@@ -96,7 +96,17 @@ public abstract class AuditableActionExecuterAbstractBase extends ActionExecuter
if (auditable)
{
getAuditService().registerAuditEvent(this.getActionDefinition().getName(), this.getActionDefinition().getTitle());
// get the details of the action
String name = getActionDefinition().getName();
String title = getActionDefinition().getTitle();
if (title == null || title.isEmpty())
{
// default to name if no title available
title = name;
}
// register audit event
getAuditService().registerAuditEvent(title, name);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -16,10 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.report.action;
import java.io.Serializable;
import java.util.Map;
package org.alfresco.module.org_alfresco_module_rm.action.impl;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
@@ -36,16 +33,20 @@ import org.apache.commons.lang.StringUtils;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Base class for the report action classes
* File report generic action.
*
* @author Tuna Aksoy
* @since 2.2
*/
public abstract class BaseReportAction extends RMActionExecuterAbstractBase implements ReportModel
public class FileReportAction extends RMActionExecuterAbstractBase implements ReportModel
{
/** action name */
public static final String NAME = "fileReport";
/** Constants for the parameters passed from the UI */
public static final String REPORT_TYPE = "reportType";
public static final String DESTINATION = "destination";
public static final String MIMETYPE= "mimetype";
/** I18N */
private static final String MSG_PARAM_NOT_SUPPLIED = "rm.action.parameter-not-supplied";
@@ -67,28 +68,30 @@ public abstract class BaseReportAction extends RMActionExecuterAbstractBase impl
@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{
// TODO check that the actionedUponNodeRef is in a state to generate a destruction report
// ie: is it eligable for destruction .. use fileDestructionReport capability!
// TODO allow the mimetype of the report to be specified as a parameter
// get the mimetype of the report
String mimetype = (String)action.getParameterValue(MIMETYPE);
if (mimetype == null || mimetype.isEmpty())
{
mimetype = MimetypeMap.MIMETYPE_HTML;
}
// get the report type
QName reportType = getReportType(action);
Report report = reportService.generateReport(reportType, actionedUponNodeRef, MimetypeMap.MIMETYPE_HTML, addProperties(actionedUponNodeRef));
// get the destination
NodeRef destination = getDestination(action);
// generate the report
Report report = reportService.generateReport(reportType, actionedUponNodeRef, mimetype);
// file the report
NodeRef filedReport = reportService.fileReport(destination, report);
// return the report name
String filedReportName = (String) nodeService.getProperty(filedReport, ContentModel.PROP_NAME);
action.setParameterValue(ActionExecuterAbstractBase.PARAM_RESULT, filedReportName);
}
/**
* Gives other action classes to pass additional properties for the template model
*
* @return Properties which are passed to the template model
*/
protected abstract Map<String, Serializable> addProperties(NodeRef nodeRef);
/**
* Retrieves the value of the given parameter. If the parameter has not been passed from the UI an error will be thrown
*

View File

@@ -1181,7 +1181,7 @@ public class RecordsManagementAuditServiceImpl extends AbstractLifecycleBean
{
List<AuditEvent> listAuditEvents = new ArrayList<AuditEvent>(this.auditEvents.size());
listAuditEvents.addAll(this.auditEvents.values());
Collections.sort(listAuditEvents, new AuditEvent());
Collections.sort(listAuditEvents);
return listAuditEvents;
}

View File

@@ -18,10 +18,9 @@
*/
package org.alfresco.module.org_alfresco_module_rm.audit.event;
import java.util.Comparator;
import org.alfresco.module.org_alfresco_module_rm.audit.RecordsManagementAuditService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.util.ParameterCheck;
import org.springframework.extensions.surf.util.I18NUtil;
@@ -32,7 +31,7 @@ import org.springframework.extensions.surf.util.I18NUtil;
* @author Roy Wetherall
* @since 1.0
*/
public class AuditEvent implements RecordsManagementModel, Comparator<AuditEvent>
public class AuditEvent implements RecordsManagementModel, Comparable<AuditEvent>
{
/** Name */
protected String name;
@@ -55,15 +54,19 @@ public class AuditEvent implements RecordsManagementModel, Comparator<AuditEvent
* Init method
*/
public void init()
{
{
ParameterCheck.mandatory("name", name);
ParameterCheck.mandatory("label", label);
recordsManagementAuditService.registerAuditEvent(this);
}
/**
* Default constructor
* Default constructor.
*/
public AuditEvent()
{
{
// do nothing
}
/**
@@ -74,6 +77,9 @@ public class AuditEvent implements RecordsManagementModel, Comparator<AuditEvent
*/
public AuditEvent(String name, String label)
{
ParameterCheck.mandatory("name", name);
ParameterCheck.mandatory("label", label);
this.name = name;
this.label = label;
}
@@ -116,11 +122,14 @@ public class AuditEvent implements RecordsManagementModel, Comparator<AuditEvent
}
/**
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
* Compare by label.
*
* @param compare compare to audit event
* @return int
*/
@Override
public int compare(AuditEvent first, AuditEvent second)
public int compareTo(AuditEvent compare)
{
return first.getLabel().compareTo(second.getLabel());
return getLabel().compareTo(compare.getLabel());
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.patch.common;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.role.Role;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Abstract implementation of capability patch.
*
* @author Roy Wetherall
* @since 2.2
*/
public abstract class CapabilityPatch extends AbstractModulePatch
{
/** File plan service */
private FilePlanService filePlanService;
/** File plan role service */
private FilePlanRoleService filePlanRoleService;
/** Capability service */
private CapabilityService capabilityService;
/**
* @param filePlanRoleService file plan role service
*/
public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService)
{
this.filePlanRoleService = filePlanRoleService;
}
/**
* @param capabilityService capability service
*/
public void setCapabilityService(CapabilityService capabilityService)
{
this.capabilityService = capabilityService;
}
/**
* @param filePlanService file plan service
*/
public void setFilePlanService(FilePlanService filePlanService)
{
this.filePlanService = filePlanService;
}
/**
* Helper method to get the file plans
*
* @return Set of file plan node references
*/
protected Set<NodeRef> getFilePlans()
{
return filePlanService.getFilePlans();
}
/**
* Adds a new capability to the specified roles.
*
* @param filePlan file plan
* @param capabilityName capability name
* @param roles roles
*/
protected void addCapability(NodeRef filePlan, String capabilityName, String ... roles)
{
Capability capability = capabilityService.getCapability(capabilityName);
if (capability == null)
{
throw new AlfrescoRuntimeException("Can't patch capabilities, because capability " + capabilityName + " does not exist.");
}
for (String roleName : roles)
{
Role role = filePlanRoleService.getRole(filePlan, roleName);
if (role != null)
{
// get the roles current capabilities
Set<Capability> capabilities = role.getCapabilities();
// only update if the capability is missing
if (!capabilities.contains(capability))
{
if (logger.isDebugEnabled())
{
logger.debug(" ... adding capability " + capabilityName + " to role " + role.getName());
}
capabilities.add(capability);
filePlanRoleService.updateRole(filePlan, role.getName(), role.getDisplayLabel(), capabilities);
}
}
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch#applyInternal()
*/
@Override
public void applyInternal()
{
Set<NodeRef> filePlans = getFilePlans();
if (logger.isDebugEnabled())
{
logger.debug(" ... updating " + filePlans.size() + " file plans");
}
for (NodeRef filePlan : filePlans)
{
if (logger.isDebugEnabled())
{
logger.debug(" ... updating file plan " + filePlan.toString());
}
// apply the capability patch to each file plan
applyCapabilityPatch(filePlan);
}
}
protected abstract void applyCapabilityPatch(NodeRef filePlan);
}

View File

@@ -18,15 +18,8 @@
*/
package org.alfresco.module.org_alfresco_module_rm.patch.v22;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.capability.Capability;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch;
import org.alfresco.module.org_alfresco_module_rm.patch.common.CapabilityPatch;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.module.org_alfresco_module_rm.role.Role;
import org.alfresco.service.cmr.repository.NodeRef;
/**
@@ -35,128 +28,29 @@ import org.alfresco.service.cmr.repository.NodeRef;
* @author Tuna Aksoy
* @since 2.2
*/
public class RMv22CapabilityPatch extends AbstractModulePatch
public class RMv22CapabilityPatch extends CapabilityPatch
{
/** File plan service */
private FilePlanService filePlanService;
/** File plan role service */
private FilePlanRoleService filePlanRoleService;
/** Capability service */
private CapabilityService capabilityService;
/**
* @param filePlanRoleService file plan role service
* @see org.alfresco.module.org_alfresco_module_rm.patch.common.CapabilityPatch#applyCapabilityPatch(org.alfresco.service.cmr.repository.NodeRef)
*/
public void setFilePlanRoleService(FilePlanRoleService filePlanRoleService)
protected void applyCapabilityPatch(NodeRef filePlan)
{
this.filePlanRoleService = filePlanRoleService;
}
/**
* @param capabilityService capability service
*/
public void setCapabilityService(CapabilityService capabilityService)
{
this.capabilityService = capabilityService;
}
/**
* @param filePlanService file plan service
*/
public void setFilePlanService(FilePlanService filePlanService)
{
this.filePlanService = filePlanService;
}
/**
* Helper method to get the file plans
*
* @return Set of file plan node references
*/
protected Set<NodeRef> getFilePlans()
{
return filePlanService.getFilePlans();
}
/**
* Adds a new capability to the specified roles.
*
* @param filePlan file plan
* @param capabilityName capability name
* @param roles roles
*/
protected void addCapability(NodeRef filePlan, String capabilityName, String ... roles)
{
Capability capability = capabilityService.getCapability(capabilityName);
if (capability == null)
{
throw new AlfrescoRuntimeException("Unable to bootstrap RMv21 capabilities, because capability " + capabilityName + " does not exist.");
}
for (String roleName : roles)
{
Role role = filePlanRoleService.getRole(filePlan, roleName);
if (role != null)
{
// get the roles current capabilities
Set<Capability> capabilities = role.getCapabilities();
// only update if the capability is missing
if (!capabilities.contains(capability))
{
if (logger.isDebugEnabled())
{
logger.debug(" ... adding capability " + capabilityName + " to role " + role.getName());
}
capabilities.add(capability);
filePlanRoleService.updateRole(filePlan, role.getName(), role.getDisplayLabel(), capabilities);
}
}
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch#applyInternal()
*/
@Override
public void applyInternal()
{
Set<NodeRef> filePlans = getFilePlans();
if (logger.isDebugEnabled())
{
logger.debug(" ... updating " + filePlans.size() + " file plans");
}
for (NodeRef filePlan : filePlans)
{
if (logger.isDebugEnabled())
{
logger.debug(" ... updating file plan " + filePlan.toString());
}
// add new capability
addCapability(filePlan,
"FileDestructionReport",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
addCapability(filePlan,
"CreateHold",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
addCapability(filePlan,
"AddToHold",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
addCapability(filePlan,
"RemoveFromHold",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
}
// add new capability
addCapability(filePlan,
"FileDestructionReport",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
addCapability(filePlan,
"CreateHold",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
addCapability(filePlan,
"AddToHold",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
addCapability(filePlan,
"RemoveFromHold",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.patch.v22;
import org.alfresco.module.org_alfresco_module_rm.patch.common.CapabilityPatch;
import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* RM v2.2 patch to add FileHoldReport capability.
*
* @author Roy Wetherall
* @since 2.2
*/
public class RMv22FileHoldReportCapabilityPatch extends CapabilityPatch
{
/**
* @see org.alfresco.module.org_alfresco_module_rm.patch.common.CapabilityPatch#applyCapabilityPatch(org.alfresco.service.cmr.repository.NodeRef)
*/
protected void applyCapabilityPatch(NodeRef filePlan)
{
// add new capability
addCapability(filePlan,
"FileHoldReport",
FilePlanRoleService.ROLE_ADMIN,
FilePlanRoleService.ROLE_RECORDS_MANAGER);
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.patch.v22;
import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
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.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* Adds the hold report.
*
* @author Roy Wetherall
* @since 2.2
*/
public class RMv22HoldReportPatch extends AbstractModulePatch
{
/** Report template path */
private static final String REPORT_TEMPLATE_PATH = "alfresco/module/org_alfresco_module_rm/bootstrap/report/report_rmr_holdReport.html.ftl";
/** Report template config node IDs */
private static final NodeRef REPORT_FOLDER = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "rm_report_templates");
private static final NodeRef REPORT = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "rmr_holdReport");
/** Node service */
private NodeService nodeService;
/** Content service */
private ContentService contentService;
/**
* @param nodeService node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param contentService content service
*/
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch#applyInternal()
*/
@Override
public void applyInternal()
{
if (!nodeService.exists(REPORT))
{
// get the assoc qname
QName assocQName = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName.createValidLocalName("report_rmr_holdReport.html.ftl"));
// build the node properties
Map<QName, Serializable> props = new HashMap<QName, Serializable>(4);
props.put(ContentModel.PROP_DESCRIPTION, "Hold report template.");
props.put(ContentModel.PROP_TITLE, "Hold Report Template");
props.put(ContentModel.PROP_NAME, "report_rmr_holdReport.html.ftl");
props.put(ContentModel.PROP_NODE_UUID, "rmr_holdReport");
// create the node
ChildAssociationRef node = nodeService.createNode(
REPORT_FOLDER,
ContentModel.ASSOC_CONTAINS,
assocQName,
ContentModel.TYPE_CONTENT,
props);
// put the content
ContentWriter writer = contentService.getWriter(node.getChildRef(), ContentModel.PROP_CONTENT, true);
InputStream is = getClass().getClassLoader().getResourceAsStream(REPORT_TEMPLATE_PATH);
writer.putContent(is);
}
}
}

View File

@@ -32,12 +32,24 @@ import org.alfresco.service.namespace.QName;
*/
public interface Report
{
/**
* @return {@link QName} report type
*/
QName getReportType();
/**
* @return {@link String} report name
*/
String getReportName();
/**
* @return {@link Map}<{@link QName},{@link Serializable}> report properties
*/
Map<QName, Serializable> getReportProperties();
/**
* @return {@link ContentReader} content reader to report content
*/
ContentReader getReportContent();
}

View File

@@ -18,21 +18,28 @@
*/
package org.alfresco.module.org_alfresco_module_rm.report;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* Report generator interface.
*
* @author Roy Wetherall
* @since 2.1
*/
public interface ReportGenerator
{
/**
* @return {@link QName} report type
*/
QName getReportType();
/**
* Generate report.
*
* @param reportedUponNodeRef
* @param mimetype
* @return
*/
Report generateReport(NodeRef reportedUponNodeRef, String mimetype);
Report generateReport(NodeRef reportedUponNodeRef, String mimetype, Map<String, Serializable> properties);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -24,14 +24,26 @@ import org.alfresco.service.namespace.QName;
* Helper class containing records management report qualified names
*
* @author Roy Wetherall
* @since 2.1
*/
public interface ReportModel
{
// Namespace details
/** Namespace details */
String RMR_URI = "http://www.alfresco.org/model/recordsmanagementreport/1.0";
String RMR_PREFIX = "rmr";
/** base report type */
QName TYPE_REPORT = QName.createQName(RMR_URI, "report");
/** destruction report type */
QName TYPE_DESTRUCTION_REPORT = QName.createQName(RMR_URI, "destructionReport");
/** transfer report type */
QName TYPE_TRANSFER_REPORT = QName.createQName(RMR_URI, "transferReport");
/**
* hold report type
* @since 2.2
*/
QName TYPE_HOLD_REPORT = QName.createQName(RMR_URI, "holdReport");
}

View File

@@ -18,8 +18,6 @@
*/
package org.alfresco.module.org_alfresco_module_rm.report;
import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -43,36 +41,31 @@ public interface ReportService
/**
* Get a list of the available report types.
*
* @return
* @return {@link Set}<{@link QName}> list of the available report types
*/
Set<QName> getReportTypes();
/**
* Generate a report of the given type and reported upon node reference.
*
*
* @param reportType
* @param reportedUponNodeRef
* @return
* @param reportType report type
* @param reportedUponNodeRef reported upon node reference
* @return {@link Report} generated report
*/
Report generateReport(QName reportType, NodeRef reportedUponNodeRef);
/**
* Generate a report for a specified mimetype.
*
* @see #generateReport(QName, NodeRef)
*
* @param reportType
* @param reportedUponNodeRef
* @return
* @param reportType report type
* @param reportedUponNodeRef report upon node reference
* @param mimetype report mimetype
* @return {@link Report} generated report
*/
Report generateReport(QName reportType, NodeRef reportedUponNodeRef, String mimetype);
/**
* @param reportType
* @param reportedUponNodeRef
* @param mimetype
* @param properties
* @return
*/
Report generateReport(QName reportType, NodeRef reportedUponNodeRef, String mimetype, Map<String, Serializable> properties);
/**
* File report in the given destination. If the given node reference is a file plan node
* reference the report will be filed in the unfiled records container.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -18,7 +18,6 @@
*/
package org.alfresco.module.org_alfresco_module_rm.report;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -95,20 +94,6 @@ public class ReportServiceImpl extends ServiceBaseImpl
ParameterCheck.mandatory("reportedUponNodeRef", reportedUponNodeRef);
ParameterCheck.mandatoryString("mimetype", mimetype);
return generateReport(reportType, reportedUponNodeRef, mimetype, new HashMap<String, Serializable>(1));
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.ReportService#generateReport(QName, NodeRef, String, Map)
*/
@Override
public Report generateReport(QName reportType, NodeRef reportedUponNodeRef, String mimetype, Map<String, Serializable> properties)
{
ParameterCheck.mandatory("reportType", reportType);
ParameterCheck.mandatory("reportedUponNodeRef", reportedUponNodeRef);
ParameterCheck.mandatoryString("mimetype", mimetype);
ParameterCheck.mandatory("properties", properties);
// get the generator
ReportGenerator generator = registry.get(reportType);
@@ -119,7 +104,7 @@ public class ReportServiceImpl extends ServiceBaseImpl
}
// generate the report
return generator.generateReport(reportedUponNodeRef, mimetype, properties);
return generator.generateReport(reportedUponNodeRef, mimetype);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -19,9 +19,9 @@
package org.alfresco.module.org_alfresco_module_rm.report.generator;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.report.Report;
import org.alfresco.module.org_alfresco_module_rm.report.ReportGenerator;
import org.alfresco.module.org_alfresco_module_rm.report.ReportService;
@@ -32,79 +32,119 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
/**
* Base report generator.
*
* @author Roy Wetherall
* @since 2.1
*/
public abstract class BaseReportGenerator implements ReportGenerator
{
/** report service */
protected ReportService reportService;
/** namespace service */
protected NamespaceService namespaceService;
protected String reportTypeName;
/** report type qualified name */
protected QName reportType;
/**
* @param reportService report service
*/
public void setReportService(ReportService reportService)
{
this.reportService = reportService;
}
/**
* @param namespaceService namespace service
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
public void setReportTypeName(String reportTypeName)
/**
* @param reportType report type
*/
public void setReportType(QName reportType)
{
this.reportTypeName = reportTypeName;
this.reportType = reportType;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.ReportGenerator#getReportType()
*/
@Override
public QName getReportType()
{
return reportType;
}
/**
* Init method
*/
public void init()
{
// convert type name to QName
reportType = QName.createQName(reportTypeName, namespaceService);
// ensure required values have been set
ParameterCheck.mandatory("reportType", reportType);
// register report generator
reportService.registerReportGenerator(this);
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.ReportGenerator#generateReport(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.util.Map)
*/
@Override
public Report generateReport(NodeRef reportedUponNodeRef, String mimetype)
{
ParameterCheck.mandatory("reportedUponNodeRef", reportedUponNodeRef);
ParameterCheck.mandatoryString("mimetype", mimetype);
return generateReport(reportedUponNodeRef, mimetype, new HashMap<String, Serializable>(1));
}
@Override
public Report generateReport(NodeRef reportedUponNodeRef, String mimetype, Map<String, Serializable> properties)
{
ParameterCheck.mandatory("reportedUponNodeRef", reportedUponNodeRef);
ParameterCheck.mandatoryString("mimetype", mimetype);
ParameterCheck.mandatory("properties", properties);
String reportName = generateReportName(reportedUponNodeRef);
Map<QName, Serializable> reportProperties = generateReportProperties(reportedUponNodeRef);
ContentReader contentReader = generateReportContent(reportedUponNodeRef, mimetype, properties);
// check the applicability of the report generator for the given reported upon node
checkReportApplicability(reportedUponNodeRef);
// generate the report name
String reportName = generateReportName(reportedUponNodeRef, mimetype);
// generate the report meta-data
Map<QName, Serializable> reportProperties = generateReportMetadata(reportedUponNodeRef);
// generate the report content
ContentReader contentReader = generateReportContent(reportedUponNodeRef, mimetype, generateReportTemplateContext(reportedUponNodeRef));
// return the report information object
return new ReportInfo(reportType, reportName, reportProperties, contentReader);
}
/**
* Checks whether the report generator is applicable given the reported upon node reference.
* <p>
* Throws AlfrescoRuntimeException if applicability fails, with reason.
*
* @param reportedUponNodeRef reported upon node reference
* @throws AlfrescoRuntimeException if applicability check fails
*/
protected abstract void checkReportApplicability(NodeRef reportedUponNodeRef) throws AlfrescoRuntimeException;
protected abstract String generateReportName(NodeRef reportedUponNodeRef);
/**
* Generate the report name
*/
protected abstract String generateReportName(NodeRef reportedUponNodeRef, String mimetype);
protected Map<QName, Serializable> generateReportProperties(NodeRef reportedUponNodeRef)
{
// default implementation
return new HashMap<QName, Serializable>(0);
}
/**
* Generate the report template context.
*/
protected abstract Map<String, Serializable> generateReportTemplateContext(NodeRef reportedUponNodeRef);
/**
* Generate report meta-data
*/
protected abstract Map<QName, Serializable> generateReportMetadata(NodeRef reportedUponNodeRef);
/**
* Generate report content
*/
protected abstract ContentReader generateReportContent(NodeRef reportedUponNodeRef, String mimetype, Map<String, Serializable> properties);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -19,21 +19,28 @@
package org.alfresco.module.org_alfresco_module_rm.report.generator;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.action.parameter.ParameterProcessorComponent;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.admin.SysAdminParams;
import org.alfresco.repo.i18n.StaticMessageLookup;
import org.alfresco.repo.model.Repository;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
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.repository.TemplateService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.UrlUtil;
import org.springframework.extensions.surf.util.I18NUtil;
@@ -45,12 +52,18 @@ import org.springframework.extensions.surf.util.I18NUtil;
*/
public class DeclarativeReportGenerator extends BaseReportGenerator
{
/** message lookups */
protected static final String MSG_REPORT = "report.default";
/** template lookup root */
protected static final NodeRef TEMPLATE_ROOT = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "rm_report_templates");
/** model keys */
protected static final String KEY_NODE = "node";
protected static final String KEY_CHILDREN = "children";
/** applicable reported upon types */
protected Set<QName> applicableTypes;
/** content service */
protected ContentService contentService;
@@ -67,12 +80,23 @@ public class DeclarativeReportGenerator extends BaseReportGenerator
/** repository helper */
protected Repository repository;
/** parameter processor component */
protected ParameterProcessorComponent parameterProcessorComponent;
/** node service */
protected NodeService nodeService;
/** dictionary service */
protected DictionaryService dictionaryService;
/** sys admin params */
protected SysAdminParams sysAdminParams;
/**
* @param applicableTypes applicable types
*/
public void setApplicableTypes(Set<QName> applicableTypes)
{
this.applicableTypes = applicableTypes;
}
/**
* @param mimetypeService mimetype service
*/
@@ -106,11 +130,19 @@ public class DeclarativeReportGenerator extends BaseReportGenerator
}
/**
* @param parameterProcessorComponent parameter processor component
* @param nodeService node service
*/
public void setParameterProcessorComponent(ParameterProcessorComponent parameterProcessorComponent)
public void setNodeService(NodeService nodeService)
{
this.parameterProcessorComponent = parameterProcessorComponent;
this.nodeService = nodeService;
}
/**
* @param dictionaryService dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
@@ -128,16 +160,47 @@ public class DeclarativeReportGenerator extends BaseReportGenerator
{
this.sysAdminParams = sysAdminParams;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.generator.BaseReportGenerator#generateReportName(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
protected String generateReportName(NodeRef reportedUponNodeRef)
protected String generateReportName(NodeRef reportedUponNodeRef, String mimetype)
{
String reportTypeName = reportType.getPrefixedQName(namespaceService).getPrefixString().replace(":", "_");
String value = I18NUtil.getMessage("report." + reportTypeName + ".name");
return parameterProcessorComponent.process(value, reportedUponNodeRef);
// get the file extension based on the mimetype
String extension = mimetypeService.getExtension(mimetype);
// get the name of the reported updon node ref
String name = (String)nodeService.getProperty(reportedUponNodeRef, ContentModel.PROP_NAME);
// build default report name
StringBuilder builder = new StringBuilder();
builder.append(getReportDisplayLabel());
if (name != null & !name.isEmpty())
{
builder.append(" - ").append(name);
}
builder.append(".").append(extension);
return builder.toString();
}
/**
* Helper method to get the report types display label
*
* @return {@link String} report type display label
*/
private String getReportDisplayLabel()
{
String result = I18NUtil.getMessage(MSG_REPORT);
TypeDefinition typeDef = dictionaryService.getType(reportType);
if (typeDef != null)
{
result = typeDef.getTitle(new StaticMessageLookup());
}
return result;
}
/**
@@ -165,6 +228,14 @@ public class DeclarativeReportGenerator extends BaseReportGenerator
return contentWriter.getReader();
}
/**
* Create template model.
*
* @param templateNodeRef
* @param reportedUponNodeRef
* @param properties
* @return
*/
protected Map<String, Serializable> createTemplateModel(NodeRef templateNodeRef, NodeRef reportedUponNodeRef, Map<String, Serializable> properties)
{
Map<String, Serializable> model = new HashMap<String, Serializable>();
@@ -214,8 +285,6 @@ public class DeclarativeReportGenerator extends BaseReportGenerator
// get localise template
return fileFolderService.getLocalizedSibling(reportTemplateNodeRef);
}
/**
@@ -239,4 +308,52 @@ public class DeclarativeReportGenerator extends BaseReportGenerator
return sb.toString();
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.generator.BaseReportGenerator#checkReportApplicability(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
protected void checkReportApplicability(NodeRef reportedUponNodeRef) throws AlfrescoRuntimeException
{
if (applicableTypes != null && applicableTypes.size() != 0)
{
boolean isTypeApplicable = false;
QName type = nodeService.getType(reportedUponNodeRef);
for (QName applicableType : applicableTypes)
{
if (dictionaryService.isSubClass(type, applicableType))
{
isTypeApplicable = true;
break;
}
}
if (!isTypeApplicable)
{
// throw an exception
throw new AlfrescoRuntimeException("Can't generate report, because the provided reported upon node reference is type " + type.toString() +
" which is not an applicable type for a " + reportType.toString() + " report.");
}
}
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.generator.BaseReportGenerator#generateReportTemplateContext(org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("unchecked")
@Override
protected Map<String, Serializable> generateReportTemplateContext(NodeRef reportedUponNodeRef)
{
return Collections.EMPTY_MAP;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.generator.BaseReportGenerator#generateReportMetadata(org.alfresco.service.cmr.repository.NodeRef)
*/
@SuppressWarnings("unchecked")
@Override
protected Map<QName, Serializable> generateReportMetadata(NodeRef reportedUponNodeRef)
{
return Collections.EMPTY_MAP;
}
}

View File

@@ -45,6 +45,14 @@ import org.springframework.extensions.surf.util.ParameterCheck;
/** content reader */
private ContentReader reportContent;
/**
* Default constructor.
*
* @param reportType report type
* @param reportName report name
* @param reportProperties report properties
* @param reportContent report content reader
*/
public ReportInfo(QName reportType, String reportName, Map<QName, Serializable> reportProperties, ContentReader reportContent)
{
ParameterCheck.mandatory("reportType", reportType);
@@ -57,22 +65,35 @@ import org.springframework.extensions.surf.util.ParameterCheck;
this.reportContent = reportContent;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.Report#getReportType()
*/
public QName getReportType()
{
return reportType;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.Report#getReportName()
*/
@Override
public String getReportName()
{
return reportName;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.Report#getReportProperties()
*/
@Override
public Map<QName, Serializable> getReportProperties()
{
return reportProperties;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.Report#getReportContent()
*/
@Override
public ContentReader getReportContent()
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.report.action;
package org.alfresco.module.org_alfresco_module_rm.report.generator.transfer;
import java.io.Serializable;
import java.util.Map;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.report.action;
package org.alfresco.module.org_alfresco_module_rm.report.generator.transfer;
import java.io.Serializable;
import java.util.ArrayList;
@@ -27,7 +27,9 @@ import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.report.generator.DeclarativeReportGenerator;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
@@ -35,21 +37,33 @@ import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.lang.StringUtils;
/**
* Transfer report action
*
* Transfer report generator.
*
* @author Tuna Aksoy
* @author Roy Wetherall
* @since 2.2
*/
public class TransferReportAction extends BaseReportAction
public class TransferReportGenerator extends DeclarativeReportGenerator
{
/** Action name */
public static final String NAME = "transferReport";
/** dispotion service */
protected DispositionService dispositionService;
/**
* @param dispositionService disposition service
*/
public void setDispositionService(DispositionService dispositionService)
{
this.dispositionService = dispositionService;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.generator.DeclarativeReportGeneratorUnitTest#generateReportTemplateContext(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
protected Map<String, Serializable> addProperties(NodeRef nodeRef)
protected Map<String, Serializable> generateReportTemplateContext(NodeRef reportedUponNodeRef)
{
// Get all 'transferred' nodes
List<TransferNode> transferNodes = getTransferNodes(nodeRef);
List<TransferNode> transferNodes = getTransferNodes(reportedUponNodeRef);
// Get the disposition authority
String dispositionAuthority = getDispositionAuthority(transferNodes);
@@ -215,4 +229,5 @@ public class TransferReportAction extends BaseReportAction
}
return dispositionAuthority == null ? StringUtils.EMPTY : dispositionAuthority;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.util;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
/**
* Custom property editor registrar.
*
* @author Roy Wetherall
* @since 2.2
*/
public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar
{
/** namespace service */
private NamespaceService namespaceService;
/**
* @param namespaceService namespace service
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @see org.springframework.beans.PropertyEditorRegistrar#registerCustomEditors(org.springframework.beans.PropertyEditorRegistry)
*/
@Override
public void registerCustomEditors(PropertyEditorRegistry registry)
{
// add custom QName editor
registry.registerCustomEditor(QName.class, new QNameTypeEditor(namespaceService));
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.util;
import java.beans.PropertyEditorSupport;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* QName type editor.
*
* @author Roy Wetherall
* @since 2.2
*/
public class QNameTypeEditor extends PropertyEditorSupport
{
/** namespace service */
private NamespaceService namespaceService;
/**
* @param namespaceService namespace service
*/
public QNameTypeEditor(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
*/
@Override
public void setAsText(String text) throws IllegalArgumentException
{
// convert prefix string to QName
setValue(QName.createQName(text, namespaceService));
}
}

View File

@@ -21,6 +21,7 @@ package org.alfresco.module.org_alfresco_module_rm.test.integration;
import org.alfresco.module.org_alfresco_module_rm.test.integration.dod.DoD5015TestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.event.EventTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.issue.IssueTestSuite;
import org.alfresco.module.org_alfresco_module_rm.test.integration.report.ReportTestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@@ -37,7 +38,8 @@ import org.junit.runners.Suite.SuiteClasses;
{
DoD5015TestSuite.class,
IssueTestSuite.class,
EventTestSuite.class
EventTestSuite.class,
ReportTestSuite.class
})
public class IntegrationTestSuite
{

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.test.integration.report;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.module.org_alfresco_module_rm.report.Report;
import org.alfresco.module.org_alfresco_module_rm.report.ReportModel;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.springframework.extensions.webscripts.GUID;
/**
* Hold report integration tests.
* <p>
* Relates to:
* - https://issues.alfresco.com/jira/browse/RM-1211
*
* @author Roy Wetherall
* @since 2.2
*/
public class HoldReportTest extends BaseRMTestCase implements ReportModel
{
@Override
protected boolean isRecordTest()
{
return true;
}
/**
* ensure that 'rmr:holdReport' is in the list of those available
*/
public void testHoldReportTypeAvailable()
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
private Set<QName> reportTypes;
public void when()
{
reportTypes = reportService.getReportTypes();
}
public void then()
{
assertNotNull(reportTypes);
assertTrue(reportTypes.contains(TYPE_HOLD_REPORT));
}
});
}
/**
* given that the reported upon node is not a hold, ensure that an error is raised when
* the report is generated.
*/
public void testReportedUponNodeIsNotAHold()
{
doBehaviourDrivenTest(new BehaviourDrivenTest(AlfrescoRuntimeException.class)
{
private NodeRef reportedUponNodeRef;
public void given()
{
reportedUponNodeRef = recordFolderService.createRecordFolder(rmContainer, GUID.generate());
}
public void when()
{
reportService.generateReport(TYPE_HOLD_REPORT, reportedUponNodeRef);
}
public void after()
{
// remove created folder
nodeService.deleteNode(reportedUponNodeRef);
}
});
}
/**
* Given a hold that contains items, ensure the report is generated as expected
*/
public void testGenerateHoldReport()
{
doBehaviourDrivenTest(new BehaviourDrivenTest()
{
private static final String HOLD_NAME = "holdName";
private static final String HOLD_REASON = "holdReason";
private static final String HOLD_DESCRIPTION = "holdDescription";
private static final String FOLDER1_NAME = "folder1Name";
private NodeRef hold;
private NodeRef folder1;
private Report report;
public void given()
{
// crate a hold
hold = holdService.createHold(filePlan, HOLD_NAME, HOLD_REASON, HOLD_DESCRIPTION);
// add some items to the hold
folder1 = recordFolderService.createRecordFolder(rmContainer, FOLDER1_NAME);
holdService.addToHold(hold, folder1);
holdService.addToHold(hold, recordOne);
}
public void when()
{
report = reportService.generateReport(TYPE_HOLD_REPORT, hold, MimetypeMap.MIMETYPE_HTML);
}
public void then()
{
assertNotNull(report);
assertEquals(TYPE_HOLD_REPORT, report.getReportType());
assertTrue(report.getReportProperties().isEmpty());
// check the name has been generated correctly
assertNotNull(report.getReportName());
assertTrue(report.getReportName().contains("Hold Report"));
assertTrue(report.getReportName().contains(HOLD_NAME));
assertTrue(report.getReportName().contains(".html"));
// check the content reader
ContentReader reader = report.getReportContent();
assertNotNull(reader);
assertEquals(MimetypeMap.MIMETYPE_HTML, reader.getMimetype());
// check the content
String reportContent = reader.getContentString();
assertNotNull(reportContent);
assertTrue(reportContent.contains(HOLD_NAME));
assertTrue(reportContent.contains(HOLD_REASON));
assertTrue(reportContent.contains(HOLD_DESCRIPTION));
assertTrue(reportContent.contains(FOLDER1_NAME));
assertTrue(reportContent.contains("one"));
}
public void after()
{
holdService.deleteHold(hold);
nodeService.deleteNode(folder1);
}
});
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2013 Alfresco Software Limited.
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
@@ -16,28 +16,23 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.report.action;
package org.alfresco.module.org_alfresco_module_rm.test.integration.report;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
/**
* Destruction report action
* Report integration test suite
*
* @author Tuna Aksoy
* @author Roy Wetherall
* @since 2.2
*/
public class DestructionReportAction extends BaseReportAction
@RunWith(Suite.class)
@SuiteClasses(
{
HoldReportTest.class
})
public class ReportTestSuite
{
/** Action name */
public static final String NAME = "destructionReport";
@Override
protected Map<String, Serializable> addProperties(NodeRef nodeRef)
{
return new HashMap<String, Serializable>(1);
}
}

View File

@@ -19,7 +19,6 @@
package org.alfresco.module.org_alfresco_module_rm.test.service;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -28,12 +27,10 @@ import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementAction
import org.alfresco.module.org_alfresco_module_rm.action.impl.CompleteEventAction;
import org.alfresco.module.org_alfresco_module_rm.action.impl.CutOffAction;
import org.alfresco.module.org_alfresco_module_rm.action.impl.DestroyAction;
import org.alfresco.module.org_alfresco_module_rm.action.impl.FileReportAction;
import org.alfresco.module.org_alfresco_module_rm.action.impl.TransferAction;
import org.alfresco.module.org_alfresco_module_rm.report.Report;
import org.alfresco.module.org_alfresco_module_rm.report.ReportModel;
import org.alfresco.module.org_alfresco_module_rm.report.action.DestructionReportAction;
import org.alfresco.module.org_alfresco_module_rm.report.action.TransferNode;
import org.alfresco.module.org_alfresco_module_rm.report.action.TransferReportAction;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase;
import org.alfresco.module.org_alfresco_module_rm.test.util.CommonRMTestUtils;
import org.alfresco.repo.content.MimetypeMap;
@@ -84,7 +81,7 @@ public class ReportServiceImplTest extends BaseRMTestCase implements ReportModel
System.out.println(destructionReport.getReportContent().getContentString());
// Transfer Report
Report transferReport = generateTransfertReport();
Report transferReport = reportService.generateReport(TYPE_TRANSFER_REPORT, getTransferObject(), MimetypeMap.MIMETYPE_HTML);
System.out.println(transferReport.getReportName());
System.out.println(transferReport.getReportContent().getContentString());
@@ -128,22 +125,7 @@ public class ReportServiceImplTest extends BaseRMTestCase implements ReportModel
{
return reportService.generateReport(TYPE_DESTRUCTION_REPORT, rmFolder);
}
/**
* Helper method to generate a transfer report
*
* @return Transfer report
*/
private Report generateTransfertReport()
{
Map<String, Serializable> properties = new HashMap<String, Serializable>(2);
ArrayList<TransferNode> transferNodes = new ArrayList<TransferNode>(1);
String dispositionAuthority = StringUtils.EMPTY;
properties.put("transferNodes", transferNodes);
properties.put("dispositionAuthority", dispositionAuthority);
return reportService.generateReport(TYPE_TRANSFER_REPORT, getTransferObject(), MimetypeMap.MIMETYPE_HTML, properties);
}
/**
* Helper method to file a destruction report
*
@@ -162,7 +144,7 @@ public class ReportServiceImplTest extends BaseRMTestCase implements ReportModel
*/
private NodeRef fileTransferReport()
{
Report transferReport = generateTransfertReport();
Report transferReport = reportService.generateReport(TYPE_TRANSFER_REPORT, getTransferObject(), MimetypeMap.MIMETYPE_HTML);
return reportService.fileReport(filePlan, transferReport);
}
@@ -181,9 +163,9 @@ public class ReportServiceImplTest extends BaseRMTestCase implements ReportModel
rmActionService.executeRecordsManagementAction(rmFolder, DestroyAction.NAME);
Map<String, Serializable> fileReportParams = new HashMap<String, Serializable>(2);
fileReportParams.put(DestructionReportAction.REPORT_TYPE, "rmr:destructionReport");
fileReportParams.put(DestructionReportAction.DESTINATION, filePlan.toString());
rmActionService.executeRecordsManagementAction(rmFolder, DestructionReportAction.NAME, fileReportParams);
fileReportParams.put(FileReportAction.REPORT_TYPE, "rmr:destructionReport");
fileReportParams.put(FileReportAction.DESTINATION, filePlan.toString());
rmActionService.executeRecordsManagementAction(rmFolder, FileReportAction.NAME, fileReportParams);
return null;
}
});
@@ -198,9 +180,9 @@ public class ReportServiceImplTest extends BaseRMTestCase implements ReportModel
{
// Create transfer report for the transfer object
Map<String, Serializable> params = new HashMap<String, Serializable>(2);
params.put(TransferReportAction.REPORT_TYPE, "rmr:transferReport");
params.put(TransferReportAction.DESTINATION, filePlan.toString());
RecordsManagementActionResult transferReportAction = rmActionService.executeRecordsManagementAction(getTransferObject(), TransferReportAction.NAME, params);
params.put(FileReportAction.REPORT_TYPE, "rmr:transferReport");
params.put(FileReportAction.DESTINATION, filePlan.toString());
RecordsManagementActionResult transferReportAction = rmActionService.executeRecordsManagementAction(getTransferObject(), FileReportAction.NAME, params);
// Check transfer report result
String transferReportName = (String) transferReportAction.getValue();
assertFalse(StringUtils.isBlank(transferReportName));

View File

@@ -810,49 +810,99 @@ public abstract class BaseRMTestCase extends RetryingTransactionHelperTestCase
}
}
/**
* Execute behaviour driven test.
*
* @param test
*/
protected void doBehaviourDrivenTest(BehaviourDrivenTest test)
{
test.run();
}
/**
* Behaviour driven test.
*
* @author Roy Wetherall
* @since 2.2
*/
protected abstract class BehaviourDrivenTest
{
public abstract void given();
protected Class<?> expectedException;
public abstract void when();
public BehaviourDrivenTest()
{
}
public abstract void then();
public BehaviourDrivenTest(Class<?> expectedException)
{
this.expectedException = expectedException;
}
public void given() { /** empty implementation */ }
public void when() { /** empty implementation */ }
public void then() { /** empty implementation */ }
public void after() { /** empty implementation */ }
public void run()
{
doTestInTransaction(new VoidTest()
{
@Override
public void runImpl() throws Exception
{
given();
}
});
doTestInTransaction(new VoidTest()
try
{
doTestInTransaction(new VoidTest()
{
@Override
public void runImpl() throws Exception
{
given();
}
});
@Override
public void runImpl() throws Exception
if (expectedException == null)
{
when();
doTestInTransaction(new VoidTest()
{
@Override
public void runImpl() throws Exception
{
when();
}
});
doTestInTransaction(new VoidTest()
{
@Override
public void runImpl() throws Exception
{
then();
}
});
}
});
doTestInTransaction(new VoidTest()
{
@Override
public void runImpl() throws Exception
else
{
then();
doTestInTransaction(new FailureTest(expectedException)
{
@Override
public void run() throws Exception
{
when();
}
});
}
});
}
finally
{
doTestInTransaction(new VoidTest()
{
@Override
public void runImpl() throws Exception
{
after();
}
});
}
}
}
}

View File

@@ -0,0 +1,212 @@
/*
* Copyright (C) 2005-2014 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.module.org_alfresco_module_rm.action.impl;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.report.Report;
import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest;
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
/**
* Unit test for file report action.
*
* @author Roy Wetherall
* @since 2.2
*/
public class FileReportActionUnitTest extends BaseUnitTest
{
/** report name */
private static final String REPORT_NAME = "testReportName";
/** actioned upon node reference */
private NodeRef actionedUponNodeRef;
/** mocked action */
private @Mock Action mockedAction;
/** mocked report */
private @Mock Report mockedReport;
/** file report action */
private @InjectMocks FileReportAction fileReportAction;
/**
* @see org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest#before()
*/
@Override
public void before()
{
super.before();
// actioned upon node reference
actionedUponNodeRef = generateRecord();
// mocked action
fileReportAction.setAuditable(false);
}
/**
* Helper to mock an action parameter value
*/
private void mockActionParameterValue(String name, String value)
{
doReturn(value).when(mockedAction).getParameterValue(name);
}
/**
* given the destination is not set, ensure that an exception is thrown
*/
@Test
public void destinationNotSet()
{
// == given ==
// set action parameter values
mockActionParameterValue(FileReportAction.MIMETYPE, MimetypeMap.MIMETYPE_HTML);
mockActionParameterValue(FileReportAction.REPORT_TYPE, "rma:destructionReport");
// expected exception
exception.expect(AlfrescoRuntimeException.class);
// == when ==
// execute action
fileReportAction.execute(mockedAction, actionedUponNodeRef);
// == then ==
verifyZeroInteractions(mockedReportService, mockedNodeService);
}
/**
* given no report type set, ensure that an exception is thrown
*/
@Test
public void reportTypeNotSet()
{
// == given ==
// set action parameter values
mockActionParameterValue(FileReportAction.MIMETYPE, MimetypeMap.MIMETYPE_HTML);
mockActionParameterValue(FileReportAction.DESTINATION, generateNodeRef().toString());
// expected exception
exception.expect(AlfrescoRuntimeException.class);
// == when ==
// execute action
fileReportAction.execute(mockedAction, actionedUponNodeRef);
// == then ==
verifyZeroInteractions(mockedReportService, mockedNodeService);
}
/**
* given the file report action is executed, ensure the service interactions and returned result
* are correct.
*/
@Test
public void fileReport()
{
// == given ==
// data
NodeRef destination = generateNodeRef();
NodeRef filedReport = generateNodeRef();
String reportType = "rma:destructionReport";
QName reportTypeQName = QName.createQName(RM_URI, "destructionReport");
String mimetype = MimetypeMap.MIMETYPE_HTML;
// set action parameter values
mockActionParameterValue(FileReportAction.MIMETYPE, mimetype);
mockActionParameterValue(FileReportAction.DESTINATION, destination.toString());
mockActionParameterValue(FileReportAction.REPORT_TYPE, reportType);
// setup service interactions
doReturn(mockedReport).when(mockedReportService).generateReport(reportTypeQName, actionedUponNodeRef, mimetype);
doReturn(filedReport).when(mockedReportService).fileReport(destination, mockedReport);
doReturn(REPORT_NAME).when(mockedNodeService).getProperty(filedReport, ContentModel.PROP_NAME);
// == when ==
// execute action
fileReportAction.execute(mockedAction, actionedUponNodeRef);
// == then ==
// verify interactions
verify(mockedReportService, times(1)).generateReport(reportTypeQName, actionedUponNodeRef, mimetype);
verify(mockedReportService, times(1)).fileReport(destination, mockedReport);
verify(mockedNodeService, times(1)).getProperty(filedReport, ContentModel.PROP_NAME);
verify(mockedAction, times(1)).setParameterValue(ActionExecuterAbstractBase.PARAM_RESULT, REPORT_NAME);
}
/**
* given the file report action is executed with no mimetype set, ensure that a report is generated
* with the default mimetype.
*/
@Test
public void fileReportDefaultMimetype()
{
// == given ==
// data
NodeRef destination = generateNodeRef();
NodeRef filedReport = generateNodeRef();
String reportType = "rma:destructionReport";
QName reportTypeQName = QName.createQName(RM_URI, "destructionReport");
String mimetype = MimetypeMap.MIMETYPE_HTML;
// set action parameter values
mockActionParameterValue(FileReportAction.DESTINATION, destination.toString());
mockActionParameterValue(FileReportAction.REPORT_TYPE, reportType);
// setup service interactions
doReturn(mockedReport).when(mockedReportService).generateReport(reportTypeQName, actionedUponNodeRef, mimetype);
doReturn(filedReport).when(mockedReportService).fileReport(destination, mockedReport);
doReturn(REPORT_NAME).when(mockedNodeService).getProperty(filedReport, ContentModel.PROP_NAME);
// == when ==
// execute action
fileReportAction.execute(mockedAction, actionedUponNodeRef);
// == then ==
// verify interactions
verify(mockedReportService, times(1)).generateReport(reportTypeQName, actionedUponNodeRef, mimetype);
verify(mockedReportService, times(1)).fileReport(destination, mockedReport);
verify(mockedNodeService, times(1)).getProperty(filedReport, ContentModel.PROP_NAME);
verify(mockedAction, times(1)).setParameterValue(ActionExecuterAbstractBase.PARAM_RESULT, REPORT_NAME);
}
}

View File

@@ -18,6 +18,7 @@
*/
package org.alfresco.module.org_alfresco_module_rm.test;
import org.alfresco.module.org_alfresco_module_rm.action.impl.FileReportActionUnitTest;
import org.alfresco.module.org_alfresco_module_rm.capability.declarative.condition.HoldCapabilityConditionUnitTest;
import org.alfresco.module.org_alfresco_module_rm.forms.RecordsManagementTypeFormFilterUnitTest;
import org.alfresco.module.org_alfresco_module_rm.hold.HoldServiceImplUnitTest;
@@ -62,7 +63,10 @@ import org.junit.runners.Suite.SuiteClasses;
HoldPutUnitTest.class,
// capability conditions
HoldCapabilityConditionUnitTest.class
HoldCapabilityConditionUnitTest.class,
// action implementations
FileReportActionUnitTest.class
})
public class AllUnitTestSuite
{

View File

@@ -37,6 +37,7 @@ import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService;
import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel;
import org.alfresco.module.org_alfresco_module_rm.record.RecordService;
import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService;
import org.alfresco.module.org_alfresco_module_rm.report.ReportService;
import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
@@ -82,24 +83,25 @@ public class BaseUnitTest implements RecordsManagementModel
protected NodeRef record;
/** core service mocks */
@Mock(name="nodeService") protected NodeService mockedNodeService;
@Mock(name="dictionaryService") protected DictionaryService mockedDictionaryService;
@Mock(name="namespaceService") protected NamespaceService mockedNamespaceService;
@Mock(name="identifierService") protected IdentifierService mockedIdentifierService;
@Mock(name="permissionService") protected PermissionService mockedPermissionService;
@Mock(name="ownableService") protected OwnableService mockedOwnableService;
@Mock(name="searchService") protected SearchService mockedSearchService;
@Mock(name="retryingTransactionHelper") protected RetryingTransactionHelper mockedRetryingTransactionHelper;
@Mock(name="nodeService") protected NodeService mockedNodeService;
@Mock(name="dictionaryService") protected DictionaryService mockedDictionaryService;
@Mock(name="namespaceService") protected NamespaceService mockedNamespaceService;
@Mock(name="identifierService") protected IdentifierService mockedIdentifierService;
@Mock(name="permissionService") protected PermissionService mockedPermissionService;
@Mock(name="ownableService") protected OwnableService mockedOwnableService;
@Mock(name="searchService") protected SearchService mockedSearchService;
@Mock(name="retryingTransactionHelper") protected RetryingTransactionHelper mockedRetryingTransactionHelper;
/** rm service mocks */
@Mock(name="filePlanService") protected FilePlanService mockedFilePlanService;
@Mock(name="recordFolderService") protected RecordFolderService mockedRecordFolderService;
@Mock(name="recordService") protected RecordService mockedRecordService;
@Mock(name="holdService") protected HoldService mockedHoldService;
@Mock(name="filePlanService") protected FilePlanService mockedFilePlanService;
@Mock(name="recordFolderService") protected RecordFolderService mockedRecordFolderService;
@Mock(name="recordService") protected RecordService mockedRecordService;
@Mock(name="holdService") protected HoldService mockedHoldService;
@Mock(name="recordsManagementActionService") protected RecordsManagementActionService mockedRecordsManagementActionService;
@Mock(name="reportService") protected ReportService mockedReportService;
/** application context mock */
@Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext;
@Mock(name="applicationContext") protected ApplicationContext mockedApplicationContext;
/** expected exception rule */
@Rule