use of org.alfresco.repo.template.ISO8601DateFormatMethod in project alfresco-repository by Alfresco.
the class FeedTaskProcessor method process.
public void process(int jobTaskNode, long minSeq, long maxSeq, RepoCtx ctx) throws Exception {
long startTime = System.currentTimeMillis();
if (logger.isDebugEnabled()) {
logger.debug("Process: jobTaskNode '" + jobTaskNode + "' from seq '" + minSeq + "' to seq '" + maxSeq + "' on this node from grid job.");
}
ActivityPostEntity selector = new ActivityPostEntity();
selector.setJobTaskNode(jobTaskNode);
selector.setMinId(minSeq);
selector.setMaxId(maxSeq);
selector.setStatus(ActivityPostEntity.STATUS.POSTED.toString());
List<ActivityPostEntity> activityPosts = null;
int totalGenerated = 0;
try {
activityPosts = selectPosts(selector);
if (logger.isDebugEnabled()) {
logger.debug("Process: " + activityPosts.size() + " activity posts");
}
// local caches for this run of activity posts
// site -> site members
Map<String, Set<String>> siteConnectedUsers = new HashMap<String, Set<String>>();
// user -> followers
Map<Pair<String, String>, Set<String>> followerConnectedUsers = new HashMap<Pair<String, String>, Set<String>>();
// <user, site> -> true/false (note: used when following, implied as true for site members)
Map<Pair<String, String>, Boolean> canUserReadSite = new HashMap<Pair<String, String>, Boolean>();
Map<String, List<FeedControlEntity>> userFeedControls = new HashMap<String, List<FeedControlEntity>>();
List<String> fmTemplates = Arrays.asList(new String[] { "activities/org/alfresco/generic.json.ftl" });
// for each activity post ...
for (ActivityPostEntity activityPost : activityPosts) {
String postingUserId = activityPost.getUserId();
String activityType = activityPost.getActivityType();
if (fmTemplates.size() == 0) {
logger.error("Skipping activity post " + activityPost.getId() + " since no specific/generic templates for activityType: " + activityType);
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
continue;
}
Map<String, Object> model = null;
try {
model = JSONtoFmModel.convertJSONObjectToMap(activityPost.getActivityData());
} catch (JSONException je) {
logger.error("Skipping activity post " + activityPost.getId() + " due to invalid activity data: ", je);
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
continue;
}
String nodeRefStr = (String) model.get(PostLookup.JSON_NODEREF);
try {
// If a nodeRef is present, then it must be valid.
if (nodeRefStr != null) {
// Attempt to create a nodeRef, making use of the constructor's validation.
new NodeRef(nodeRefStr);
}
} catch (Exception e) {
logger.error("Skipping activity post " + activityPost.getId() + " due to invalid nodeRef: " + nodeRefStr);
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
continue;
}
// note: for MT share, site id should already be mangled - in addition to extra tenant domain info
String thisSite = activityPost.getSiteNetwork();
String tenantDomain = (String) model.get(PostLookup.JSON_TENANT_DOMAIN);
if (thisSite != null) {
if (tenantDomain != null) {
thisSite = getTenantName(thisSite, tenantDomain);
} else {
// for backwards compatibility
tenantDomain = getTenantDomain(thisSite);
}
}
if (tenantDomain == null) {
tenantDomain = TenantService.DEFAULT_DOMAIN;
}
model.put(ActivityFeedEntity.KEY_ACTIVITY_FEED_TYPE, activityPost.getActivityType());
model.put(ActivityFeedEntity.KEY_ACTIVITY_FEED_SITE, thisSite);
model.put("userId", activityPost.getUserId());
model.put("id", activityPost.getId());
// post date rather than time that feed is generated
model.put("date", activityPost.getPostDate());
model.put("xmldate", new ISO8601DateFormatMethod());
model.put("repoEndPoint", ctx.getRepoEndPoint());
// Get recipients of this post
Set<String> recipients = null;
try {
recipients = getRecipients(ctx, thisSite, activityPost.getUserId(), tenantDomain, siteConnectedUsers, followerConnectedUsers, canUserReadSite);
} catch (Exception e) {
logger.error("Skipping activity post " + activityPost.getId() + " since failed to get recipients: ", e);
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.ERROR);
continue;
}
try {
startTransaction();
if (logger.isTraceEnabled()) {
logger.trace("Process: " + recipients.size() + " candidate connections for activity post " + activityPost.getId());
}
int excludedConnections = 0;
for (String recipient : recipients) {
List<FeedControlEntity> feedControls = null;
if (!recipient.equals("")) {
// Get user's feed controls
feedControls = userFeedControls.get(recipient);
if (feedControls == null) {
feedControls = getFeedControls(recipient);
userFeedControls.put(recipient, feedControls);
}
}
// filter based on opt-out feed controls (if any)
if (!acceptActivity(activityPost, feedControls)) {
excludedConnections++;
} else {
// node read permission check (if nodeRef is present)
if (!canRead(ctx, recipient, model)) {
excludedConnections++;
continue;
}
for (String fmTemplate : fmTemplates) {
String formatFound = FeedTaskProcessor.FEED_FORMAT_JSON;
ActivityFeedEntity feed = new ActivityFeedEntity();
// MNT-9104 If username contains uppercase letters the action of joining a site will not be displayed in "My activities"
if (!userNamesAreCaseSensitive) {
recipient = recipient.toLowerCase();
postingUserId = postingUserId.toLowerCase();
}
feed.setFeedUserId(recipient);
feed.setPostUserId(postingUserId);
feed.setActivityType(activityType);
String activitySummary = null;
// allows JSON to simply pass straight through
activitySummary = activityPost.getActivityData();
if (!activitySummary.equals("")) {
if (activitySummary.length() > ActivityFeedDAO.MAX_LEN_ACTIVITY_SUMMARY) {
logger.warn("Skip feed entry (activity post " + activityPost.getId() + ") since activity summary - exceeds " + ActivityFeedDAO.MAX_LEN_ACTIVITY_SUMMARY + " chars: " + activitySummary);
} else {
feed.setActivitySummary(activitySummary);
feed.setSiteNetwork(thisSite);
feed.setAppTool(activityPost.getAppTool());
feed.setPostDate(activityPost.getPostDate());
feed.setPostId(activityPost.getId());
feed.setFeedDate(new Date());
// Insert activity feed
// ignore returned feedId
insertFeedEntry(feed);
totalGenerated++;
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Empty template result for activityType '" + activityType + "' using format '" + formatFound + "' hence skip feed entry (activity post " + activityPost.getId() + ")");
}
}
}
}
}
updatePostStatus(activityPost.getId(), ActivityPostEntity.STATUS.PROCESSED);
commitTransaction();
if (logger.isDebugEnabled()) {
logger.debug("Processed: " + (recipients.size() - excludedConnections) + " connections for activity post " + activityPost.getId() + " (excluded " + excludedConnections + ")");
}
} finally {
endTransaction();
}
}
} catch (SQLException se) {
logger.error(se);
throw se;
} finally {
int postCnt = activityPosts == null ? 0 : activityPosts.size();
// TODO i18n info message
StringBuilder sb = new StringBuilder();
sb.append("Generated ").append(totalGenerated).append(" activity feed entr").append(totalGenerated == 1 ? "y" : "ies");
sb.append(" for ").append(postCnt).append(" activity post").append(postCnt != 1 ? "s" : "").append(" (in ").append(System.currentTimeMillis() - startTime).append(" msecs)");
logger.info(sb.toString());
}
}
Aggregations