package is.idega.idegaweb.egov.bpm.business;
import is.idega.idegaweb.egov.application.business.ApplicationBusiness;
import is.idega.idegaweb.egov.application.data.Application;
import is.idega.idegaweb.egov.bpm.IWBundleStarter;
import is.idega.idegaweb.egov.bpm.cases.messages.CaseUserFactory;
import is.idega.idegaweb.egov.bpm.cases.messages.CaseUserImpl;
import is.idega.idegaweb.egov.bpm.servlet.CommentViewerRedirector;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.webdav.lib.Ace;
import org.apache.webdav.lib.Privilege;
import org.apache.webdav.lib.WebdavResource;
import org.jbpm.JbpmContext;
import org.jbpm.JbpmException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.idega.block.article.bean.ArticleCommentAttachmentInfo;
import com.idega.block.article.bean.CommentEntry;
import com.idega.block.article.bean.CommentsViewerProperties;
import com.idega.block.article.business.CommentsPersistenceManager;
import com.idega.block.article.business.DefaultCommentsPersistenceManager;
import com.idega.block.article.component.ArticleCommentAttachmentStatisticsViewer;
import com.idega.block.article.component.CommentsViewer;
import com.idega.block.article.data.Comment;
import com.idega.block.article.data.CommentHome;
import com.idega.block.process.business.CaseBusiness;
import com.idega.block.process.data.Case;
import com.idega.block.process.variables.Variable;
import com.idega.block.process.variables.VariableDataType;
import com.idega.block.rss.business.RSSBusiness;
import com.idega.builder.bean.AdvancedProperty;
import com.idega.builder.business.BuilderLogic;
import com.idega.business.file.FileDownloadNotificationProperties;
import com.idega.content.business.ContentConstants;
import com.idega.core.accesscontrol.business.AccessController;
import com.idega.core.accesscontrol.business.NotLoggedOnException;
import com.idega.core.contact.data.Email;
import com.idega.core.file.data.ICFile;
import com.idega.data.IDOLookup;
import com.idega.idegaweb.IWApplicationContext;
import com.idega.idegaweb.IWMainApplication;
import com.idega.idegaweb.IWResourceBundle;
import com.idega.idegaweb.egov.bpm.data.CaseProcInstBind;
import com.idega.idegaweb.egov.bpm.data.dao.CasesBPMDAO;
import com.idega.jbpm.BPMContext;
import com.idega.jbpm.JbpmCallback;
import com.idega.jbpm.data.ProcessManagerBind;
import com.idega.jbpm.exe.BPMFactory;
import com.idega.jbpm.exe.ProcessInstanceW;
import com.idega.jbpm.exe.TaskInstanceW;
import com.idega.jbpm.rights.Right;
import com.idega.jbpm.utils.JBPMConstants;
import com.idega.jbpm.variables.BinaryVariable;
import com.idega.presentation.IWContext;
import com.idega.slide.business.IWSlideService;
import com.idega.slide.util.AccessControlEntry;
import com.idega.slide.util.AccessControlList;
import com.idega.slide.util.IWSlideConstants;
import com.idega.slide.util.WebdavRootResource;
import com.idega.user.business.UserBusiness;
import com.idega.user.data.User;
import com.idega.util.CoreConstants;
import com.idega.util.CoreUtil;
import com.idega.util.IOUtil;
import com.idega.util.ListUtil;
import com.idega.util.StringUtil;
import com.idega.util.URIUtil;
import com.sun.syndication.feed.WireFeed;
import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Feed;
import com.sun.syndication.feed.synd.SyndFeed;
@Scope(BeanDefinition.SCOPE_SINGLETON)
@Service(BPMCommentsPersistenceManager.SPRING_BEAN_IDENTIFIER)
public class BPMCommentsPersistenceManager extends DefaultCommentsPersistenceManager implements CommentsPersistenceManager {
private static final Logger LOGGER = Logger.getLogger(BPMCommentsPersistenceManager.class.getName());
public static final String SPRING_BEAN_IDENTIFIER = "bpmCommentsPersistenceManagerImpl";
@Autowired
private BPMFactory bpmFactory;
@Autowired
private BPMContext bpmContext;
@Autowired
private CaseUserFactory caseUserFactory;
@Autowired
private CasesBPMDAO casesDAO;
@Override
public String getLinkToCommentsXML(final String processInstanceIdStr) {
return getLinkToCommentFolder(processInstanceIdStr) + "comments.xml";
}
private String getLinkToCommentFolder(final String prcInstId) {
if (StringUtil.isEmpty(prcInstId)) {
return null;
}
final Long processInstanceId = Long.valueOf(prcInstId);
final String storePath = getBpmContext().execute(new JbpmCallback() {
public Object doInJbpm(JbpmContext context) throws JbpmException {
String processName = context.getProcessInstance(processInstanceId).getProcessDefinition().getName();
String storePath = new StringBuilder(JBPMConstants.BPM_PATH).append(CoreConstants.SLASH).append(processName).append("/processComments/")
.append(prcInstId).append(CoreConstants.SLASH).toString();
return storePath;
}
});
return storePath;
}
@Override
public boolean hasRightsToViewComments(String processInstanceId) {
return hasRightsToViewComments(getConvertedValue(processInstanceId));
}
@Override
public boolean hasRightsToViewComments(Long processInstanceId) {
if (processInstanceId == null) {
return false;
}
if (hasFullRightsForComments(processInstanceId)) {
return true;
}
User currentUser = getCurrentUser();
if (currentUser != null) {
return hasRightToViewComments(processInstanceId, currentUser);
}
return false;
}
@Override
public boolean hasRightsToWriteComments(Long identifier) {
if (identifier == null)
return false;
User currentUser = getCurrentUser();
if (currentUser != null) {
return hasRightToWriteComments(identifier, currentUser);
}
return false;
}
protected boolean hasRightToWriteComments(Long processInstanceId, User user) {
return getBpmFactory().getRolesManager().canWriteComments(processInstanceId, user);
}
protected boolean hasRightToViewComments(Long processInstanceId, User user) {
return getBpmFactory().getRolesManager().canSeeComments(processInstanceId, user);
}
private Long getConvertedValue(String value) {
if (StringUtil.isEmpty(value)) {
return null;
}
try {
return Long.valueOf(value);
} catch (NumberFormatException e) {
e.printStackTrace();
}
return null;
}
public BPMFactory getBpmFactory() {
return bpmFactory;
}
public void setBpmFactory(BPMFactory bpmFactory) {
this.bpmFactory = bpmFactory;
}
private IWResourceBundle getResourceBundle(IWContext iwc) {
return iwc.getIWMainApplication().getBundle(IWBundleStarter.IW_BUNDLE_IDENTIFIER).getResourceBundle(iwc);
}
@Transactional(readOnly = true)
@Override
public String getFeedTitle(IWContext iwc, String processInstanceId) {
String defaultTitle = "Comments of process";
String localizedTitle = null;
try {
ProcessInstanceW piw = getProcessInstance(processInstanceId);
ApplicationBusiness appBusiness = getApplicationBusiness(iwc);
Collection<Application> apps = appBusiness.getApplicationHome().findAllByApplicationUrl(piw.getProcessDefinitionW().getProcessDefinition().getName());
if (ListUtil.isEmpty(apps)) {
return defaultTitle;
}
localizedTitle = appBusiness.getApplicationName(apps.iterator().next(), iwc.getCurrentLocale());
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Error getting localized name for process instance's ('"+defaultTitle+"') application", e);
}
localizedTitle = StringUtil.isEmpty(localizedTitle) ? defaultTitle : localizedTitle;
return getResourceBundle(iwc).getLocalizedString("feed.comments_of_process", defaultTitle) + (defaultTitle.equals(localizedTitle) ?
CoreConstants.EMPTY : (" " + localizedTitle));
}
@Override
public String getFeedSubtitle(IWContext iwc, String processInstanceId) {
return getResourceBundle(iwc).getLocalizedString("feed.all_comments_of_a_process", "All comments of a process");
}
private void updateAccessRights(IWSlideService slide, String uri) {
AccessControlList acl = null;
try {
acl = slide.getAccessControlList(uri);
if (acl == null) {
return;
}
Ace ace = new Ace(IWSlideConstants.SUBJECT_URI_AUTHENTICATED);
ace.addPrivilege(Privilege.READ);
acl.add(new AccessControlEntry(ace, AccessControlEntry.PRINCIPAL_TYPE_STANDARD));
slide.storeAccessControlList(acl, new WebdavRootResource(slide.getWebdavResourceAuthenticatedAsRoot(uri)));
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Error while updating access rights for: " + uri, e);
}
}
@Override
public Feed getCommentsFeed(String processInstanceId) {
String uri = getLinkToCommentsXML(processInstanceId);
if (StringUtil.isEmpty(uri)) {
LOGGER.warning("URI to comments feed was not constructed!");
return null;
}
IWSlideService slide = getRepository();
if (slide == null) {
LOGGER.warning("Repository is unknown!");
return null;
}
try {
if (!slide.getExistence(uri)) {
return null;
}
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Error checking resource's existence", e);
return null;
}
updateAccessRights(slide, uri);
RSSBusiness rss = getRSSBusiness();
if (rss == null) {
LOGGER.warning(RSSBusiness.class + " service is not available!");
return null;
}
User currentUser = getCurrentUser();
if (currentUser == null) {
LOGGER.warning("User is not logged in!");
return null;
}
String pathToFeed = null;
try {
pathToFeed = new StringBuilder(slide.getWebdavServerURL().getURI()).append(uri).toString();
} catch (Exception e) {
e.printStackTrace();
}
if (StringUtil.isEmpty(pathToFeed)) {
LOGGER.log(Level.SEVERE, "Error creating path to comments feed!");
return null;
}
SyndFeed comments = rss.getFeedAuthenticatedByUser(pathToFeed, currentUser);
if (comments == null) {
LOGGER.log(Level.WARNING, "Unable to get comments feed ('" + pathToFeed + "') by current (" + currentUser + ") user, trying with admin user");
comments = rss.getFeedAuthenticatedByAdmin(pathToFeed);
}
if (comments == null) {
LOGGER.log(Level.SEVERE, "Error getting comments feed ('" + pathToFeed + "') by super admin!");
return null;
}
if (comments instanceof Feed) {
return (Feed) comments;
}
WireFeed wireFeed = comments.createWireFeed();
if (wireFeed instanceof Feed) {
return (Feed) wireFeed;
}
LOGGER.warning("Object " + wireFeed + " (" + wireFeed.getClass() + ") is not instance of: " + Feed.class);
return null;
}
@Override
public boolean storeFeed(String processInstanceId, Feed comments) {
if (comments == null) {
LOGGER.warning("Comments feed is undefined!");
return false;
}
String url = getLinkToCommentsXML(processInstanceId);
if (StringUtil.isEmpty(url)) {
LOGGER.warning("Unable to resolve link to comments using process instance id: " + processInstanceId + " for comments feed: " + comments);
return false;
}
IWSlideService service = getRepository();
if (service == null) {
LOGGER.warning("Repository is undefined!");
return false;
}
String commentsContent = getFeedContent(comments);
if (commentsContent == null) {
return false;
}
String fileBase = url;
String fileName = url;
int index = url.lastIndexOf(ContentConstants.SLASH);
if (index != -1) {
fileBase = url.substring(0, index + 1);
fileName = url.substring(index + 1);
}
try {
return service.uploadFileAndCreateFoldersFromStringAsRoot(fileBase, fileName, commentsContent, ContentConstants.XML_MIME_TYPE, true);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Error storing comments feed", e);
}
LOGGER.warning("Unable to upload comments " + commentsContent + " to: " + fileBase + fileName);
return false;
}
private IWSlideService getRepository() {
return getServiceInstance(IWSlideService.class);
}
private RSSBusiness getRSSBusiness() {
return getServiceInstance(RSSBusiness.class);
}
// TODO: When access rights (to Slide resources) are fixed, use current user!
@Override
public User getUserAvailableToReadWriteCommentsFeed(IWContext iwc) {
User currentUser = null;
try {
currentUser = iwc.getCurrentUser();
} catch (NotLoggedOnException e) {
e.printStackTrace();
}
if (currentUser == null) {
return null;
}
AccessController accessController = iwc.getAccessController();
try {
if (iwc.isSuperAdmin()) {
return currentUser;
}
} catch (Exception e) {
e.printStackTrace();
}
try {
return accessController.getAdministratorUser();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public BPMContext getBpmContext() {
return bpmContext;
}
@Override
public boolean hasFullRightsForComments(String processInstanceId) {
return hasFullRightsForComments(getConvertedValue(processInstanceId));
}
@Override
public boolean hasFullRightsForComments(Long processInstanceId) {
if (processInstanceId == null) {
return false;
}
ProcessInstanceW piw = getProcessInstance(processInstanceId);
return piw.hasRight(Right.processHandler);
}
protected ProcessInstanceW getProcessInstance(String processInstanceId) {
if (StringUtil.isEmpty(processInstanceId)) {
return null;
}
return getProcessInstance(Long.valueOf(processInstanceId));
}
protected ProcessInstanceW getProcessInstance(Long processInstanceId) {
return getBpmFactory().getProcessManagerByProcessInstanceId(processInstanceId).getProcessInstance(processInstanceId);
}
public void setBpmContext(BPMContext bpmContext) {
this.bpmContext = bpmContext;
}
@Override
public String getHandlerRoleKey() {
return null; // Should be defined by extended class
}
@Override
public List<String> getPersonsToNotifyAboutComment(CommentsViewerProperties properties, Object commentId, boolean justPublished) {
Integer authorId = null;
try {
Comment comment = getComment(commentId);
authorId = comment.getAuthorId();
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error getting author for comment: " + commentId, e);
}
return getAllFeedSubscribers(properties.getIdentifier(), authorId);
}
protected boolean canReadAndWriteAllComments(Long identifier, User user) {
return false;
}
@SuppressWarnings("unchecked")
@Override
public List<? extends Entry> getEntriesToFormat(Feed comments, CommentsViewerProperties properties) {
List<Entry> allEntries = comments.getEntries();
if (ListUtil.isEmpty(allEntries)) {
return null;
}
boolean hasFullRights = hasFullRightsForComments(properties.getIdentifier());
User currentUser = getLoggedInUser();
if (currentUser == null) {
return null;
}
int userId = -1;
try {
userId = Integer.valueOf(currentUser.getId());
} catch(NumberFormatException e) {
LOGGER.warning("Error converting to number " + currentUser.getId());
return null;
}
List<Entry> filteredEntries = new ArrayList<Entry>(allEntries.size());
Map<String, Entry> entries = new HashMap<String, Entry>(allEntries.size());
for (Entry entry: allEntries) {
entries.put(entry.getId(), entry);
}
Collection<Comment> commentsByProcessInstance = null;
try {
CommentHome commentHome = (CommentHome) IDOLookup.getHome(Comment.class);
commentsByProcessInstance = commentHome.findAllCommentsByHolder(properties.getIdentifier());
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error getting comments by holder: " + properties.getIdentifier(), e);
return null;
}
if (ListUtil.isEmpty(commentsByProcessInstance)) {
return null;
}
boolean canSeeAndWriteCommentsAllComments = canReadAndWriteAllComments(getConvertedValue(properties.getIdentifier()), currentUser);
for (Comment comment: commentsByProcessInstance) {
Entry entry = entries.get(comment.getEntryId());
if (entry != null && !filteredEntries.contains(entry)) {
CommentEntry commentEntry = new CommentEntry(entry);
if (properties.isFetchFully()) {
fillWithAttachments(comment, commentEntry, properties, hasFullRights);
}
boolean visible = true;
boolean checkIfRead = false;
if (comment.isPrivateComment()) {
if (hasFullRights) {
// Handler
commentEntry.setPublishable(isRelyToComment(comment) != null);
commentEntry.setPublished(comment.isAnnouncedToPublic());
commentEntry.setReplyable(isReplyable(comment, currentUser));
commentEntry.setPrimaryKey(comment.getPrimaryKey().toString());
fillWithReaders(properties, comment, commentEntry);
} else if (comment.isAnnouncedToPublic() || canSeeAndWriteCommentsAllComments) {
// Comment was announced to public
commentEntry.setPrimaryKey(comment.getPrimaryKey().toString());
checkIfRead = true;
} else if (isReplyToPrivateComment(comment, currentUser) || canSeeAndWriteCommentsAllComments) {
// This is a reply-comment to private comment
commentEntry.setPrimaryKey(comment.getPrimaryKey().toString());
checkIfRead = true;
} else if (comment.getAuthorId().intValue() != userId || canSeeAndWriteCommentsAllComments) {
// Not this user's private comment
visible = false;
}
} else {
if (!hasFullRights && comment.isAnnouncedToPublic() || canSeeAndWriteCommentsAllComments) {
commentEntry.setPrimaryKey(comment.getPrimaryKey().toString());
checkIfRead = true;
}
if (hasFullRights) {
fillWithReaders(properties, comment, commentEntry);
}
}
if (visible) {
if (properties.isFetchFully()&& checkIfRead) {
if (!isCommentRead(comment, currentUser)) {
commentEntry.setReadable(true);
markAsRead(comment, currentUser, commentEntry);
}
}
filteredEntries.add(commentEntry);
}
}
}
return filteredEntries;
}
private void fillWithAttachments(Comment comment, CommentEntry commentEntry, CommentsViewerProperties properties, boolean fullRights) {
Collection<ICFile> attachments = comment.getAllAttachments();
if (ListUtil.isEmpty(attachments)) {
return;
}
List<BinaryVariable> processAttachments = getAllProcessAttachments(properties.getIdentifier());
String commentId = comment.getPrimaryKey().toString();
for (ICFile attachment: attachments) {
if (fullRights || isAttachmentVisible(processAttachments, attachment.getHash(), comment.isPrivateComment())) {
try {
String name = URLDecoder.decode(attachment.getName(), CoreConstants.ENCODING_UTF8);
ArticleCommentAttachmentInfo info = new ArticleCommentAttachmentInfo();
info.setName(name);
info.setUri(getUriToAttachment(commentId, attachment, null));
if (fullRights) {
info.setCommentId(commentId);
String attachmentId = attachment.getPrimaryKey().toString();
info.setAttachmentId(attachmentId);
info.setBeanIdentifier(properties.getSpringBeanIdentifier());
info.setIdentifier(properties.getIdentifier());
info.setStatisticsUri(BuilderLogic.getInstance().getUriToObject(ArticleCommentAttachmentStatisticsViewer.class, Arrays.asList(
new AdvancedProperty(ArticleCommentAttachmentStatisticsViewer.COMMENT_ID_PARAMETER, commentId),
new AdvancedProperty(ArticleCommentAttachmentStatisticsViewer.COMMENT_ATTACHMENT_ID_PARAMETER, attachmentId),
new AdvancedProperty(ArticleCommentAttachmentStatisticsViewer.IDENTIFIER_PARAMETER, properties.getIdentifier()),
new AdvancedProperty(ArticleCommentAttachmentStatisticsViewer.BEAN_IDENTIFIER_PARAMETER, properties.getSpringBeanIdentifier())
)));
}
commentEntry.addAttachment(info);
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error adding attachment's link: " + attachment.getFileUri(), e);
}
}
}
}
private boolean isAttachmentVisible(List<BinaryVariable> processAttachments, Integer hash, boolean privateComment) {
if (privateComment) {
return true;
}
if (ListUtil.isEmpty(processAttachments)) {
// No attachments for the process
return false;
}
if (hash == null) {
return false;
}
for (BinaryVariable processAttachment: processAttachments) {
if (hash.intValue() == processAttachment.getHash().intValue()) {
return true;
}
}
return false;
}
private List<BinaryVariable> getAllProcessAttachments(String processInstanceId) {
ProcessInstanceW piw = getProcessInstance(processInstanceId);
if (piw == null) {
return null;
}
return piw.getAttachments();
}
@SuppressWarnings("unchecked")
private void fillWithReaders(CommentsViewerProperties properties, Comment comment, CommentEntry commentEntry) {
if (!properties.isFetchFully()) {
return;
}
Collection<User> readBy = comment.getReadBy();
if (ListUtil.isEmpty(readBy)) {
return;
}
for (User reader: readBy) {
AdvancedProperty readerInfo = new AdvancedProperty(reader.getName());
Collection<Email> emails = reader.getEmails();
if (!ListUtil.isEmpty(emails)) {
readerInfo.setValue(emails.iterator().next().getEmailAddress());
}
commentEntry.addReader(readerInfo);
}
}
private void markAsRead(Comment comment, User user, CommentEntry commentEntry) {
try {
comment.addReadBy(user);
comment.store();
commentEntry.setReadable(false);
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error marking as read", e);
}
}
private Comment isRelyToComment(Comment comment) {
Integer replyToId = comment.getReplyForCommentId();
if (replyToId == null || replyToId < 0) {
return null;
}
return getComment(replyToId);
}
private boolean isReplyToPrivateComment(Comment comment, User user) {
Comment originalComment = isRelyToComment(comment);
if (originalComment == null) {
return false;
}
try {
if (originalComment.getAuthorId().intValue() == Integer.valueOf(user.getId()).intValue()) {
return true;
}
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error checking if current user is author of comment: " + originalComment, e);
}
return false;
}
private boolean isReplyable(Comment comment, User user) {
if (comment.isAnnouncedToPublic()) {
return false;
}
Integer replyToId = comment.getReplyForCommentId();
return replyToId == null || replyToId == -1 ? true : false;
}
private boolean isCommentRead(Comment comment, User user) {
Collection<User> readers = comment.getReadBy();
return (ListUtil.isEmpty(readers)) ? false : readers.contains(user);
}
@Override
public String getCommentFilesPath(CommentsViewerProperties properties) {
if (properties == null) {
return null;
}
return new StringBuilder(getLinkToCommentFolder(properties.getIdentifier())).append("files/").toString();
}
@Override
public Object addComment(CommentsViewerProperties properties) {
Object commentId = super.addComment(properties);
if (commentId == null) {
LOGGER.warning("Unable to create comment in DB table!");
return null;
}
Comment comment = getComment(commentId);
if (comment == null) {
return commentId;
}
Collection<ICFile> attachments = comment.getAllAttachments();
if (ListUtil.isEmpty(attachments)) {
return commentId;
}
Long prcInsId = null;
try {
prcInsId = Long.valueOf(properties.getIdentifier());
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error parsing id from: " + properties.getIdentifier(), e);
}
if (prcInsId == null) {
return commentId;
}
if (!hasFullRightsForComments(prcInsId)) {
return commentId;
}
ProcessInstanceW piw = null;
try {
piw = getBpmFactory().getProcessManagerByProcessInstanceId(prcInsId).getProcessInstance(prcInsId);
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error getting process instance by: " + prcInsId, e);
}
if (piw == null) {
return commentId;
}
TaskInstanceW task = getSubmittedTaskInstance(piw, getTaskNameForAttachments());
if (task == null) {
LOGGER.warning("Do not know for which task to attach file(s)");
return commentId;
}
IWResourceBundle iwrb = null;
try {
iwrb = IWMainApplication.getDefaultIWMainApplication().getBundle(IWBundleStarter.IW_BUNDLE_IDENTIFIER).getResourceBundle(CoreUtil.getIWContext());
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error getting " + IWResourceBundle.class, e);
}
String description = iwrb == null ? "Attached file for" : iwrb.getLocalizedString("attached_file_for", "Attached file for");
String subject = StringUtil.isEmpty(properties.getSubject()) ?
iwrb == null ? "comment" : iwrb.getLocalizedString("comment", "comment") :
properties.getSubject();
for (ICFile attachment: attachments) {
InputStream is = getInputStreamForAttachment(attachment.getFileUri());
if (is == null) {
LOGGER.warning("Unable to attach file " + attachment.getFileUri() + " for task: " + task.getTaskInstanceId() + " in process: "
+ piw.getProcessInstanceId());
} else {
Variable variable = new Variable("cmnt_attch", VariableDataType.FILE);
String name = getAttachmentName(attachment.getName());
BinaryVariable binVariable = task.addAttachment(variable, name,
new StringBuilder(description).append(CoreConstants.COLON).append(CoreConstants.SPACE).append(subject).toString(), is);
if (binVariable != null) {
attachment.setHash(binVariable.getHash());
attachment.store();
}
IOUtil.closeInputStream(is);
}
}
return commentId;
}
private InputStream getInputStreamForAttachment(String uri) {
try {
IWSlideService slide = getRepository();
WebdavResource resource = slide.getWebdavResourceAuthenticatedAsRoot(URLDecoder.decode(uri, CoreConstants.ENCODING_UTF8));
if (resource != null && resource.exists()) {
return resource.getMethodData();
}
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error getting InputStream from: " + uri, e);
}
return null;
}
private String getAttachmentName(String defaultName) {
try {
return URLDecoder.decode(defaultName, CoreConstants.ENCODING_UTF8);
} catch (UnsupportedEncodingException e) {
LOGGER.log(Level.WARNING, "Error decoding: " + defaultName);
}
return defaultName;
}
protected TaskInstanceW getSubmittedTaskInstance(ProcessInstanceW piw, String taskName) {
if (piw == null || StringUtil.isEmpty(taskName)) {
return null;
}
List<TaskInstanceW> submittedTasks = piw.getSubmittedTaskInstances();
if (ListUtil.isEmpty(submittedTasks)) {
return null;
}
TaskInstanceW latestTask = null;
for (TaskInstanceW taskInstance: submittedTasks) {
if (taskName.equals(taskInstance.getTaskInstance().getName())) {
if (latestTask == null) {
latestTask = taskInstance;
} else if (taskInstance.getTaskInstance().getCreate().after(latestTask.getTaskInstance().getCreate())) {
latestTask = taskInstance;
}
}
}
return latestTask;
}
@Override
protected String getLinkForRecipient(String recipient, CommentsViewerProperties properties) {
ProcessInstanceW piw = getProcessInstance(properties.getIdentifier());
if (piw == null) {
return super.getLinkForRecipient(recipient, properties);
}
UserBusiness userBusiness = getUserBusiness();
if (userBusiness == null) {
return super.getLinkForRecipient(recipient, properties);
}
Collection<User> recipients = userBusiness.getUsersByEmail(recipient);
if (ListUtil.isEmpty(recipients)) {
return super.getLinkForRecipient(recipient, properties);
}
CaseUserImpl caseUser = getCaseUserFactory().getCaseUser(recipients.iterator().next(), piw);
String url = caseUser.getUrlToTheCase();
if (StringUtil.isEmpty(url)) {
return super.getLinkForRecipient(recipient, properties);
}
URIUtil uriUtil = new URIUtil(url);
uriUtil.setParameter(CommentsViewer.AUTO_SHOW_COMMENTS, Boolean.TRUE.toString());
return uriUtil.getUri();
}
public CaseUserFactory getCaseUserFactory() {
return caseUserFactory;
}
public void setCaseUserFactory(CaseUserFactory caseUserFactory) {
this.caseUserFactory = caseUserFactory;
}
@Override
protected List<User> getCaseHandlers(String identifier) {
ProcessInstanceW piw = getProcessInstance(identifier);
if (piw == null) {
return null;
}
Integer handlerId = piw.getHandlerId();
if (handlerId == null) {
return null;
}
UserBusiness userBusiness = getUserBusiness();
User handler = null;
try {
handler = userBusiness.getUser(handlerId);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Error getting user by id: " + handlerId, e);
}
if (handler == null) {
return null;
}
List<User> handlers = new ArrayList<User>();
handlers.add(handler);
return handlers;
}
protected Case getCase(Long processInstanceId) {
CaseProcInstBind bind = null;
try {
bind = getCasesDAO().getCaseProcInstBindByProcessInstanceId(processInstanceId);
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error getting case for process instance: " + processInstanceId);
}
if (bind == null) {
return null;
}
try {
return getCaseBusiness(IWMainApplication.getDefaultIWApplicationContext()).getCase(bind.getCaseId());
} catch(Exception e) {
LOGGER.log(Level.WARNING, "Error getting case by id: " + bind.getCaseId(), e);
}
return null;
}
public CasesBPMDAO getCasesDAO() {
return casesDAO;
}
public void setCasesDAO(CasesBPMDAO casesDAO) {
this.casesDAO = casesDAO;
}
protected CaseBusiness getCaseBusiness(IWApplicationContext iwac) {
return getServiceInstance(iwac, CaseBusiness.class);
}
protected ApplicationBusiness getApplicationBusiness(IWApplicationContext iwac) {
return getServiceInstance(iwac, ApplicationBusiness.class);
}
@Override
public Map<String, String> getUriToDocument(FileDownloadNotificationProperties properties, String identifier, List<User> users) {
if (StringUtil.isEmpty(identifier)) {
return super.getUriToDocument(properties, identifier, users);
}
ProcessInstanceW piw = getProcessInstance(identifier);
if (piw == null) {
return super.getUriToDocument(properties, identifier, users);
}
Map<String, String> linksForUsers = new HashMap<String, String>();
for (User user: users) {
CaseUserImpl caseUser = null;
try {
caseUser = caseUserFactory.getCaseUser(user, piw);
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Error getting url to user's case for user " + user + " and process instance: " + piw.getProcessInstanceId(), e);
}
String uri = null;
if (caseUser == null) {
uri = properties.getUrl();
} else {
String url = caseUser.getUrlToTheCase();
if (StringUtil.isEmpty(url)) {
uri = properties.getUrl();
} else {
URIUtil uriUtil = new URIUtil(url);
uriUtil.setParameter(CommentsViewer.AUTO_SHOW_COMMENTS, Boolean.TRUE.toString());
uri = uriUtil.getUri();
}
}
uri = StringUtil.isEmpty(uri) ? properties.getUrl() : uri;
linksForUsers.put(user.getId(), uri);
}
return linksForUsers;
}
@Override
public String getUriForCommentLink(CommentsViewerProperties properties) {
if (properties == null) {
return super.getUriForCommentLink(properties);
}
String processInstanceId = properties.getIdentifier();
if (StringUtil.isEmpty(processInstanceId)) {
return super.getUriForCommentLink(properties);
}
URIUtil uriUtil = new URIUtil(new StringBuilder(CoreConstants.SLASH).append(CommentViewerRedirector.class.getSimpleName()).append(CoreConstants.SLASH)
.toString());
uriUtil.setParameter(CommentViewerRedirector.PARAMETER_REDIRECT_TO_COMMENT, Boolean.TRUE.toString());
uriUtil.setParameter(ProcessManagerBind.processInstanceIdParam, processInstanceId);
return uriUtil.getUri();
}
}