/*
* #%L
* Alfresco Records Management Module
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.module.org_alfresco_module_rm.report.generator;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
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.repo.security.authentication.AuthenticationUtil;
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.apache.commons.lang.StringUtils;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Declarative report generator.
*
* @author Roy Wetherall
* @since 2.1
*/
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;
/** mimetype service */
protected MimetypeService mimetypeService;
/** file folder service */
protected FileFolderService fileFolderService;
/** template service */
protected TemplateService templateService;
/** repository helper */
protected Repository repository;
/** 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
*/
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
/**
* @param fileFolderService file folder service
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/**
* @param templateService template service
*/
public void setTemplateService(TemplateService templateService)
{
this.templateService = templateService;
}
/**
* @param contentService content service
*/
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
/**
* @param nodeService node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param dictionaryService dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @param repository repository helper
*/
public void setRepository(Repository repository)
{
this.repository = repository;
}
/**
* @param sysAdminParams sys admin params
*/
public void setSysAdminParams(SysAdminParams sysAdminParams)
{
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, String mimetype)
{
// 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 (StringUtils.isNotBlank(name))
{
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;
}
/**
* @see org.alfresco.module.org_alfresco_module_rm.report.generator.BaseReportGenerator#generateReportContent(NodeRef, String, Map)
*/
@Override
protected ContentReader generateReportContent(NodeRef reportedUponNodeRef, String mimetype, Map<String, Serializable> properties)
{
// get the template
NodeRef reportTemplateNodeRef = getReportTemplate(mimetype);
// get the model
Map<String, Serializable> model = createTemplateModel(reportTemplateNodeRef, reportedUponNodeRef, properties);
// run the template
String result = templateService.processTemplate("freemarker", reportTemplateNodeRef.toString(), model);
// create the temp content
ContentWriter contentWriter = contentService.getTempWriter();
contentWriter.setEncoding("UTF-8");
contentWriter.setMimetype(mimetype);
contentWriter.putContent(result);
// return the reader to the temp content
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>();
// build the default model
NodeRef person = repository.getPerson();
templateService.buildDefaultModel(person,
repository.getCompanyHome(),
repository.getUserHome(person),
templateNodeRef,
null);
// put the reported upon node reference in the model
model.put(KEY_NODE, reportedUponNodeRef);
// context url's (handy for images and links)
model.put("url", UrlUtil.getAlfrescoUrl(sysAdminParams));
model.put(TemplateService.KEY_SHARE_URL, UrlUtil.getShareUrl(sysAdminParams));
// who and when the report was generated
model.put("reportUser", AuthenticationUtil.getRunAsUser());
Calendar now = Calendar.getInstance(I18NUtil.getContentLocale());
model.put("reportDate", SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM).format(now.getTime()));
// add additional properties
model.put("properties", (Serializable) properties);
return model;
}
/**
* Get's the report template based on the type and mimetype.
*
* @param mimetype
* @return
*/
private NodeRef getReportTemplate(String mimetype)
{
// check that the template root has been correctly bootstraped
if (!fileFolderService.exists(TEMPLATE_ROOT))
{
throw new AlfrescoRuntimeException("Unable to get report template, because the template root folder does not exist in the data dictionary.");
}
String reportTemplateName = getReportTemplateName(mimetype);
NodeRef reportTemplateNodeRef = fileFolderService.searchSimple(TEMPLATE_ROOT, reportTemplateName);
if (reportTemplateNodeRef == null)
{
throw new AlfrescoRuntimeException("Unable to get report template, because report template " + reportTemplateName + " does not exist.");
}
// get localise template
return fileFolderService.getLocalizedSibling(reportTemplateNodeRef);
}
/**
* Gets the template name based on the type and mimetype.
*
* @param mimetype
* @return
*/
private String getReportTemplateName(String mimetype)
{
String typePrefixName = reportType.getPrefixedQName(namespaceService).getPrefixString().replace(":", "_");
String extension = mimetypeService.getExtension(mimetype);
StringBuilder sb = new StringBuilder(128)
.append("report_")
.append(typePrefixName)
.append(".")
.append(extension)
.append(".ftl");
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)
{
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;
}
}