package fr.itldev.koya.activities.feed;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.activities.ActivityType;
import org.alfresco.repo.activities.feed.ActivitiesFeedModelBuilder;
import org.alfresco.repo.activities.feed.EmailUserNotifier;
import org.alfresco.repo.domain.activities.ActivityFeedEntity;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.invitation.Invitation;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.namespace.NamespaceException;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ModelUtil;
import org.alfresco.util.Pair;
import org.json.JSONException;
import fr.itldev.koya.alfservice.CompanyService;
import fr.itldev.koya.alfservice.KoyaMailService;
import fr.itldev.koya.alfservice.security.CompanyAclService;
import fr.itldev.koya.model.KoyaActivityType;
import fr.itldev.koya.model.impl.Company;
public class KoyaEmailUserNotifier extends EmailUserNotifier {
protected KoyaMailService koyaMailService;
protected CompanyAclService companyAclService;
protected CompanyService companyService;
public void setKoyaMailService(KoyaMailService koyaMailService) {
this.koyaMailService = koyaMailService;
}
public void setCompanyAclService(CompanyAclService companyAclService) {
this.companyAclService = companyAclService;
}
public void setCompanyService(CompanyService companyService) {
this.companyService = companyService;
}
private static List<String> ALLOWED_ACTIVITIES = new ArrayList<String>(
Arrays.asList(KoyaActivityType.KOYA_SPACESHARED,
KoyaActivityType.KOYA_SPACEUNUNSHARED,
ActivityType.FOLDER_ADDED, ActivityType.FILE_ADDED,
ActivityType.FILE_DELETED, ActivityType.FOLDER_DELETED,
ActivityType.FILE_UPDATED, ActivityType.SITE_USER_JOINED,
ActivityType.SITE_USER_REMOVED,
KoyaActivityType.FOLDER_UPDATED));
/**
*
* TODO process ignored activities
*
* ActivityType.SITE_USER_REMOVED ActivityType.FILES_ADDED,
* ActivityType.FOLDERS_ADDED,
*
*/
/**
* Skip User if he has a pending invitation on company
*
* @return
*/
private Boolean skipUserOnCompany(String companyName, String userName) {
List<Invitation> invitations = companyAclService.getPendingInvite(
companyName, null, userName);
return invitations != null && invitations.size() == 1;
}
public Pair<Integer, Long> notifyUser(final NodeRef personNodeRef,
String subject, Object[] subjectParams,
Map<String, String> siteNames, String shareUrl,
int repeatIntervalMins, String templateNodeRef) {
Map<QName, Serializable> personProps = nodeService
.getProperties(personNodeRef);
String feedUserId = (String) personProps
.get(ContentModel.PROP_USERNAME);
if (skipUser(personNodeRef)) {
// skip
return null;
}
// where did we get up to ?
Long feedDBID = getFeedId(personNodeRef);
// own + others (note: template can be changed to filter out user's own
// activities if needed)
if (logger.isDebugEnabled()) {
logger.debug("Get user feed entries: " + feedUserId + ", "
+ feedDBID);
}
List<ActivityFeedEntity> feedEntries = activityService
.getUserFeedEntries(feedUserId, null, false, false, null, null,
feedDBID);
if (feedEntries.size() > 0) {
List<String> allowedCompaniesForUser = AuthenticationUtil.runAs(
new AuthenticationUtil.RunAsWork<List<String>>() {
@Override
public List<String> doWork() throws Exception {
List<String> companiesNames = new ArrayList<String>();
for (Company c : companyService.list()) {
companiesNames.add(c.getName());
}
return companiesNames;
}
}, feedUserId);
Map<String, ActivitiesFeedModelBuilder> companyModelBuilder = new HashMap<>();
Map<String, Boolean> skipUserPendingInvite = new HashMap<>();
long skippedMaxId = 0;
for (ActivityFeedEntity feedEntry : feedEntries) {
String companyName = feedEntry.getSiteNetwork();
ActivitiesFeedModelBuilder modelBuilder;
if (!skipUserPendingInvite.containsKey(companyName)) {
skipUserPendingInvite.put(companyName,
skipUserOnCompany(companyName, feedUserId));
}
boolean allowedCompany = true;
/*
* Filter if company is not allowed for user
*/
if (!allowedCompaniesForUser.contains(feedEntry
.getSiteNetwork())) {
allowedCompany = false;
if (feedEntry.getId() > skippedMaxId) {
skippedMaxId = feedEntry.getId();
}
}
/*
* Filter on activity type
*
* Activity must be an allowed type to be sent by email
*/
boolean allowedActivity = true;
if (!ALLOWED_ACTIVITIES.contains(feedEntry.getActivityType())) {
logger.error("user"
+ feedUserId
+ " - Ignored activity type for email template composition : "
+ feedEntry.getActivityType() + " -> "
+ feedEntry.getId());
allowedActivity = false;
if (feedEntry.getId() > skippedMaxId) {
skippedMaxId = feedEntry.getId();
}
}
// Add activity to model if user is not skiped because of
// pending invite
if (!skipUserPendingInvite.get(companyName) && allowedActivity
&& allowedCompany) {
// select company model builder. Creates if not exists
if (!companyModelBuilder.containsKey(companyName)) {
try {
companyModelBuilder.put(companyName,
activitiesFeedModelBuilderFactory
.getObject());
} catch (Exception error) {
logger.warn("Unable to create model builder for company '"
+ companyName + "' : " + error.getMessage());
return null;
}
}
modelBuilder = companyModelBuilder.get(companyName);
try {
modelBuilder.addAcctivitiyFeedEntry(feedEntry);
} catch (JSONException je) {
// skip this feed entry
logger.warn("Skip feed entry for user (" + feedUserId
+ "): " + je.getMessage());
continue;
}
}
}
long maxFeedId = 0;
int activityCount = 0;
for (String companyName : companyModelBuilder.keySet()) {
ActivitiesFeedModelBuilder modelBuilder = companyModelBuilder
.get(companyName);
int localActivityCount = modelBuilder.activityCount();
activityCount += localActivityCount;
if (localActivityCount > 0) {
Map<String, Object> model = modelBuilder.buildModel();
model.put("siteTitles", siteNames);
model.put("repeatIntervalMins", repeatIntervalMins);
model.put("feedItemsMax", activityService.getMaxFeedItems());
// add Share info to model
model.put(TemplateService.KEY_PRODUCT_NAME,
ModelUtil.getProductName(repoAdminService));
Map<String, Serializable> personPrefixProps = new HashMap<String, Serializable>(
personProps.size());
for (QName propQName : personProps.keySet()) {
try {
String propPrefix = propQName
.toPrefixString(namespaceService);
personPrefixProps.put(propPrefix,
personProps.get(propQName));
} catch (NamespaceException ne) {
// ignore properties that do not have a registered
// namespace
logger.warn("Ignoring property '" + propQName
+ "' as it's namespace is not registered");
}
}
model.put("personProps", personPrefixProps);
if (modelBuilder.getMaxFeedId() > maxFeedId) {
maxFeedId = modelBuilder.getMaxFeedId();
}
// send with koyaMail
koyaMailService.sendUserNotifMail(personNodeRef, model,
templateNodeRef, companyName);
}
}
// update maxFeedId for skiped activities
if (skippedMaxId > maxFeedId) {
maxFeedId = skippedMaxId;
}
return new Pair<Integer, Long>(activityCount, maxFeedId);
}
return null;
}
}