/*
* Copyright (C) 2013 Atol Conseils et D�veloppements.
* http://www.atolcd.com/
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.atolcd.alfresco.web.scripts.shareStats;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.model.ForumModel;
import org.alfresco.repo.site.SiteModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.site.SiteInfo;
import org.alfresco.service.cmr.site.SiteService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.util.Assert;
import com.atolcd.alfresco.AuditCount;
import com.atolcd.alfresco.AuditEntry;
import com.atolcd.alfresco.AuditObjectPopularity;
import com.atolcd.alfresco.AuditQueryParameters;
import com.atolcd.alfresco.helper.PermissionsHelper;
public class SelectAuditsGet extends DeclarativeWebScript implements InitializingBean {
// Logger
private static final Log logger = LogFactory.getLog(SelectAuditsGet.class);
// SqlMapClientTemplate for MyBatis calls
private SqlSessionTemplate sqlSessionTemplate;
private NodeService nodeService;
private SiteService siteService;
private static final String SELECT_BY_VIEW = "alfresco.atolcd.audit.selectByRead";
private static final String SELECT_BY_CREATED = "alfresco.atolcd.audit.selectByCreated";
private static final String SELECT_BY_UPDATED = "alfresco.atolcd.audit.selectByUpdated";
private static final String SELECT_BY_DELETED = "alfresco.atolcd.audit.selectByDeleted";
private static final String SELECT_BY_MOSTREAD = "alfresco.atolcd.audit.selectByMostRead";
private static final String SELECT_BY_MOSTUPDATED = "alfresco.atolcd.audit.selectByMostUpdated";
private static final String SELECT_TO_UPDATE = "alfresco.atolcd.audit.selectEntriesToUpdate";
static final QName TYPE_DATALIST = QName.createQName("http://www.alfresco.org/model/datalist/1.0", "dataList");
static final QName TYPE_CALENDAR_EVENT = QName.createQName("http://www.alfresco.org/model/calendar", "calendarEvent");
static final QName PROP_CALENDAR_EVENT_WHAT = QName.createQName("http://www.alfresco.org/model/calendar", "whatEvent");
static final QName TYPE_LINK = QName.createQName("http://www.alfresco.org/model/linksmodel/1.0", "link");
static final QName PROP_LINK_TITLE = QName.createQName("http://www.alfresco.org/model/linksmodel/1.0", "title");
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
public void setSiteService(SiteService siteService) {
this.siteService = siteService;
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.sqlSessionTemplate);
Assert.notNull(this.nodeService);
}
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) {
try {
Map<String, Object> model = new HashMap<String, Object>();
if (PermissionsHelper.isAuthorized(req)) {
// Check for the sqlMapClientTemplate Bean
if (this.sqlSessionTemplate != null) {
// Get the input content given into the request.
AuditQueryParameters params = buildParametersFromRequest(req);
String type = req.getParameter("type");
String stringLimit = req.getParameter("limit");
int limit = 0;
if (stringLimit != null && !stringLimit.isEmpty()) {
limit = Integer.parseInt(stringLimit);
}
checkForQuery(model, params, type, limit);
}
} else {
status.setCode(Status.STATUS_UNAUTHORIZED);
}
return model;
} catch (Exception e) {
if (logger.isDebugEnabled()) {
logger.debug(e.getMessage(), e);
}
throw new WebScriptException("[ShareStats - SelectAudits] Error in executeImpl function");
}
}
public void checkForQuery(Map<String, Object> model, AuditQueryParameters params, String type) throws SQLException, JSONException {
checkForQuery(model, params, type, 0);
}
public void checkForQuery(Map<String, Object> model, AuditQueryParameters params, String type, int limit) throws SQLException,
JSONException {
switch (queryType.valueOf(type)) {
case read:
model.put("dates", selectByDate(params, SELECT_BY_VIEW));
break;
case created:
model.put("dates", selectByDate(params, SELECT_BY_CREATED));
break;
case deleted:
model.put("dates", selectByDate(params, SELECT_BY_DELETED));
break;
case updated:
model.put("dates", selectByDate(params, SELECT_BY_UPDATED));
break;
case mostread:
model.put("popularity", selectByPopularity(params, SELECT_BY_MOSTREAD, limit));
break;
case mostupdated:
model.put("popularity", selectByPopularity(params, SELECT_BY_MOSTUPDATED, limit));
break;
}
}
@SuppressWarnings("unchecked")
public List<AuditObjectPopularity> selectByPopularity(AuditQueryParameters params, String query, int limit) {
List<AuditObjectPopularity> auditObjectPopularityList = new ArrayList<AuditObjectPopularity>();
auditObjectPopularityList = (List<AuditObjectPopularity>) sqlSessionTemplate.selectList(query, params);
logger.info("Performing " + query + " ... ");
Iterator<AuditObjectPopularity> iterator = auditObjectPopularityList.iterator();
int treatedItems = 0;
// Verify if the returned items always exist
while (iterator.hasNext() && treatedItems < limit) {
AuditObjectPopularity auditObjectPopularity = iterator.next();
try {
NodeRef nodeRef = new NodeRef(auditObjectPopularity.getAuditObject());
if (!nodeService.exists(nodeRef)) {
iterator.remove();
} else {
auditObjectPopularity.setObjectName((String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME));
auditObjectPopularity.setObjectDisplayName(getPrettyDisplayname(nodeRef));
SiteInfo si = siteService.getSite(nodeRef);
if (si != null) {
// Find in which site component is this node
Path nodePath = nodeService.getPath(nodeRef);
if (nodePath.size() > 4) {
String siteContainerQName = nodeService.getPath(nodeRef).get(4).getElementString();
auditObjectPopularity.setSiteComponent(QName.createQName(siteContainerQName).getLocalName());
}
}
treatedItems++;
}
} catch (AlfrescoRuntimeException e) {
iterator.remove();
logger.warn(e.getMessage(), e);
}
}
limit = auditObjectPopularityList.size() > limit ? limit : auditObjectPopularityList.size();
return auditObjectPopularityList.subList(0, limit);
}
@SuppressWarnings("unchecked")
public List<List<AuditCount>> selectByDate(AuditQueryParameters params, String query) {
String[] dates = params.getSlicedDates().split(",");
List<List<AuditCount>> auditCount = new ArrayList<List<AuditCount>>();
for (int i = 0; i < dates.length - 1; i++) {
params.setDateFrom(dates[i]);
params.setDateTo(dates[i + 1]);
List<AuditCount> auditSample = new ArrayList<AuditCount>();
auditSample = (List<AuditCount>) sqlSessionTemplate.selectList(query, params);
auditCount.add(auditSample);
}
logger.info("Performing " + query + " ... ");
return auditCount;
}
@SuppressWarnings("unchecked")
public List<AuditEntry> selectEntriesToUpdate() {
return (List<AuditEntry>) sqlSessionTemplate.selectList(SELECT_TO_UPDATE);
}
public AuditQueryParameters buildParametersFromRequest(WebScriptRequest req) {
try {
String dateFrom = req.getParameter("from");
String dateTo = req.getParameter("to");
AuditQueryParameters params = new AuditQueryParameters();
params.setSiteId(req.getParameter("site"));
params.setSitesId(req.getParameter("sites"));
params.setActionName(req.getParameter("action"));
params.setAppName(req.getParameter("module"));
params.setAppNames(req.getParameter("modules"));
params.setDateFrom(dateFrom);
params.setDateTo(dateTo);
params.setSlicedDates(req.getParameter("dates"));
return params;
} catch (Exception e) {
logger.error("Error building parameters", e);
return null;
}
}
private String getPrettyDisplayname(NodeRef nodeRef) {
String nodeName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
QName nodeType = nodeService.getType(nodeRef);
if (nodeType.equals(TYPE_DATALIST)) {
// DataList: use title
return (String) nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
} else if (nodeType.equals(ForumModel.TYPE_TOPIC)) {
// Discussion: find first child that have the same name
NodeRef firstTopic = nodeService.getChildByName(nodeRef, ContentModel.ASSOC_CONTAINS, nodeName);
if (firstTopic != null) {
return (String) nodeService.getProperty(firstTopic, ContentModel.PROP_TITLE);
}
} else if (nodeType.equals(TYPE_LINK)) {
// Link: use link title
return (String) nodeService.getProperty(nodeRef, PROP_LINK_TITLE);
} else if (nodeType.equals(TYPE_CALENDAR_EVENT)) {
// Event: use 'what' metadata
return (String) nodeService.getProperty(nodeRef, PROP_CALENDAR_EVENT_WHAT);
} else {
// Others: content, wiki, blog
NodeRef parentRef = nodeService.getPrimaryParent(nodeRef).getParentRef();
if (parentRef != null) {
if (nodeService.hasAspect(parentRef, SiteModel.ASPECT_SITE_CONTAINER)) {
String parentName = (String) nodeService.getProperty(parentRef, ContentModel.PROP_NAME);
if (parentName.equals("blog") || parentName.equals("wiki")) {
// For Blog or Wiki pages, we use the title
return (String) nodeService.getProperty(nodeRef, ContentModel.PROP_TITLE);
}
}
}
}
return nodeName;
}
}