This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 84d92fd3eec9fd5eb04f338f2704b012c1bf732f Author: Kevin Morin <morin@codelutin.com> Date: Fri May 12 09:26:40 2017 +0200 refs #14 création du flux atom à la création du sondage + ajout des entrées dans le flux pour l'ajout, la suppression et la modification d'un vote + ajout du bouton pour lire le flux à partir du sondage --- pollen-persistence/src/main/xmi/pollen.properties | 1 + .../org/chorem/pollen/rest/api/v1/PollApi.java | 6 ++ pollen-rest-api/src/main/resources/mapping | 2 + pollen-services/pom.xml | 6 +- .../pollen/services/service/FeedService.java | 116 +++++++++++++++++++++ .../pollen/services/service/PollService.java | 1 + .../services/service/PollenServiceSupport.java | 28 +++++ .../pollen/services/service/VoteService.java | 3 + .../pollen/services/service/mail/EmailService.java | 35 +------ .../i18n/pollen-services_en_GB.properties | 5 + .../i18n/pollen-services_fr_FR.properties | 5 + .../src/main/web/tag/poll/Poll.tag.html | 3 +- pom.xml | 8 +- 13 files changed, 181 insertions(+), 38 deletions(-) diff --git a/pollen-persistence/src/main/xmi/pollen.properties b/pollen-persistence/src/main/xmi/pollen.properties index dec4909a..73dd47bf 100644 --- a/pollen-persistence/src/main/xmi/pollen.properties +++ b/pollen-persistence/src/main/xmi/pollen.properties @@ -27,6 +27,7 @@ model.tagValue.hibernateAttributeType.String=string package.org.chorem.pollen.persistence.entity.stereotype=entity # Text org.chorem.pollen.persistence.entity.Poll.attribute.description.tagValue.hibernateAttributeType=text +org.chorem.pollen.persistence.entity.Poll.attribute.feedContent.tagValue.hibernateAttributeType=text org.chorem.pollen.persistence.entity.Choice.attribute.description.tagValue.hibernateAttributeType=text org.chorem.pollen.persistence.entity.Comment.attribute.text.tagValue.hibernateAttributeType=text # Blob diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java index 988304f7..7df49fc3 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java @@ -32,9 +32,11 @@ import org.chorem.pollen.services.bean.PollenEntityId; import org.chorem.pollen.services.bean.PollenEntityRef; import org.chorem.pollen.services.bean.VoterListBean; import org.chorem.pollen.services.bean.VoterListMemberBean; +import org.chorem.pollen.services.service.FeedService; import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.PollService; import org.debux.webmotion.server.WebMotionController; +import org.debux.webmotion.server.render.Render; import java.io.File; import java.util.List; @@ -135,4 +137,8 @@ public class PollApi extends WebMotionController { public PollBean assignPoll(PollService pollService, PollenEntityId<Poll> pollId) { return pollService.assignPollToConnectedUser(pollId.getEntityId()); } + + public Render getFeedForPoll(FeedService feedService, PollenEntityId<Poll> pollId) { + return renderAtom(feedService.getFeedForPoll(pollId.getEntityId())); + } } diff --git a/pollen-rest-api/src/main/resources/mapping b/pollen-rest-api/src/main/resources/mapping index b15faba8..96658bae 100644 --- a/pollen-rest-api/src/main/resources/mapping +++ b/pollen-rest-api/src/main/resources/mapping @@ -125,6 +125,8 @@ PUT /v1/polls/{pollId}/close PollApi.closePoll PUT /v1/polls/{pollId}/reopen PollApi.reopenPoll PUT /v1/polls/{pollId}/assign PollApi.assignPoll +GET /v1/polls/{pollId}/feed PollApi.getFeedForPoll + # PollenResourceApi GET /v1/resources/{resourceId} PollenResourceApi.getResource diff --git a/pollen-services/pom.xml b/pollen-services/pom.xml index 1df904ca..49951934 100644 --- a/pollen-services/pom.xml +++ b/pollen-services/pom.xml @@ -127,10 +127,10 @@ <artifactId>guava</artifactId> </dependency> - <!--dependency> - <groupId>rome</groupId> + <dependency> + <groupId>com.rometools</groupId> <artifactId>rome</artifactId> - </dependency--> + </dependency> <dependency> <groupId>junit</groupId> diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/FeedService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/FeedService.java new file mode 100644 index 00000000..96239861 --- /dev/null +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/FeedService.java @@ -0,0 +1,116 @@ +package org.chorem.pollen.services.service; + +import com.rometools.rome.feed.synd.SyndContent; +import com.rometools.rome.feed.synd.SyndContentImpl; +import com.rometools.rome.feed.synd.SyndEntry; +import com.rometools.rome.feed.synd.SyndEntryImpl; +import com.rometools.rome.feed.synd.SyndFeed; +import com.rometools.rome.feed.synd.SyndFeedImpl; +import com.rometools.rome.io.FeedException; +import com.rometools.rome.io.SyndFeedInput; +import com.rometools.rome.io.SyndFeedOutput; +import org.chorem.pollen.persistence.entity.Poll; +import org.chorem.pollen.persistence.entity.Vote; +import org.chorem.pollen.services.PollenTechnicalException; +import org.chorem.pollen.services.service.security.PermissionVerb; + +import java.io.StringReader; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.nuiton.i18n.I18n.n; +import static org.nuiton.i18n.I18n.t; + +/** + * @author Kevin Morin (Code Lutin) + * @since 3.0 + */ +public class FeedService extends PollenServiceSupport { + + public static final String FEED_TYPE = "atom_1.0"; + public static final String DESCRIPTION_TYPE = "text/plain"; + + public void onPollCreated(Poll poll) { + SyndFeed feed = new SyndFeedImpl(); + feed.setFeedType(FEED_TYPE); + + feed.setTitle(poll.getTitle()); + String voteUrl = getPollVoteUrl(poll); + feed.setLink(voteUrl); + feed.setDescription(poll.getDescription()); + + SyndEntry entry = new SyndEntryImpl(); + entry.setTitle(t("pollen.service.feed.pollCreated.title", poll.getCreator().getName(), poll.getTitle())); + entry.setLink(voteUrl); + entry.setPublishedDate(poll.getTopiaCreateDate()); + + SyndContent description = new SyndContentImpl(); + description.setType(DESCRIPTION_TYPE); + description.setValue(t("pollen.service.feed.pollCreated.description", + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(poll.getTopiaCreateDate()), + poll.getCreator().getName(), + poll.getTitle())); + entry.setDescription(description); + + List<SyndEntry> feedEntries = Collections.singletonList(entry); + feed.setEntries(feedEntries); + + saveFeed(poll, feed); + } + + public void onVoteAdded(Poll poll, Vote vote) { + addVoteFeedEntry(poll, vote, n("pollen.service.feed.voteAdded.title")); + } + + public void onVoteEdited(Poll poll, Vote vote) { + addVoteFeedEntry(poll, vote, n("pollen.service.feed.voteEdited.title")); + } + + public void onVoteDeleted(Poll poll, Vote vote) { + addVoteFeedEntry(poll, vote, n("pollen.service.feed.voteDeleted.title")); + } + + public SyndFeed getFeedForPoll(String pollId) { + checkNotNull(pollId); + checkPermission(PermissionVerb.readPoll, pollId); + + Poll poll = getPollService().getPoll0(pollId); + + try { + SyndFeedInput feedInput = new SyndFeedInput(true, getLocale()); + return feedInput.build(new StringReader(poll.getFeedContent())); + + } catch (FeedException e) { + throw new PollenTechnicalException("Error while reading the feed", e); + } + } + + private void addVoteFeedEntry(Poll poll, Vote vote, String messageKey) { + SyndFeed feed = getFeedForPoll(poll.getTopiaId()); + List<SyndEntry> entries = new ArrayList<>(feed.getEntries()); + + SyndEntry entry = new SyndEntryImpl(); + entry.setTitle(t(messageKey, vote.getVoter().getName())); + entry.setLink(getPollVoteUrl(poll)); + entry.setPublishedDate(vote.getTopiaCreateDate()); + + entries.add(entry); + feed.setEntries(entries); + + saveFeed(poll, feed); + } + + private void saveFeed(Poll poll, SyndFeed feed) { + try { + SyndFeedOutput output = new SyndFeedOutput(); + String feedContent = output.outputString(feed); + poll.setFeedContent(feedContent); + commit(); + + } catch (FeedException e) { + throw new PollenTechnicalException("Error while creating the feed", e); + } + } +} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java index 143408d4..45bf43df 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java @@ -227,6 +227,7 @@ public class PollService extends PollenServiceSupport { commit(); getNotificationService().onPollCreated(savedPoll); + getFeedService().onPollCreated(savedPoll); return PollenEntityRef.of(savedPoll); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java index f6076a60..62704bd4 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java @@ -33,6 +33,7 @@ import org.chorem.pollen.persistence.entity.ChoiceTopiaDao; import org.chorem.pollen.persistence.entity.CommentTopiaDao; import org.chorem.pollen.persistence.entity.FavoriteListMemberTopiaDao; import org.chorem.pollen.persistence.entity.FavoriteListTopiaDao; +import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollTopiaDao; import org.chorem.pollen.persistence.entity.PollenPrincipalTopiaDao; import org.chorem.pollen.persistence.entity.PollenResourceTopiaDao; @@ -49,6 +50,7 @@ import org.chorem.pollen.services.PollenUIContext; import org.chorem.pollen.services.bean.PaginationResultBean; import org.chorem.pollen.services.bean.PollenBean; import org.chorem.pollen.services.bean.PollenBeans; +import org.chorem.pollen.services.bean.PollenEntityId; import org.chorem.pollen.services.config.PollenServicesConfig; import org.chorem.pollen.services.service.mail.EmailService; import org.chorem.pollen.services.service.security.PermissionVerb; @@ -128,6 +130,10 @@ public abstract class PollenServiceSupport implements PollenService { return newService(NotificationService.class); } + protected FeedService getFeedService() { + return newService(FeedService.class); + } + protected PollService getPollService() { return newService(PollService.class); } @@ -447,4 +453,26 @@ public abstract class PollenServiceSupport implements PollenService { } + protected <E extends TopiaEntity> PollenEntityId<E> getPollenEntityId(E entity) { + PollenEntityId<E> pollenEntityId = PollenEntityId.newId((Class<E>) entity.getClass()); + pollenEntityId.setEntityId(entity.getTopiaId()); + pollenEntityId.encode(serviceContext.getTopiaApplicationContext().getTopiaIdFactory()); + return pollenEntityId; + } + + protected String getPollVoteUrl(Poll poll) { + return getPollVoteUrl(getPollenEntityId(poll), null); + } + + protected String getPollVoteUrl(Poll poll, String token) { + return getPollVoteUrl(getPollenEntityId(poll), token); + } + + protected String getPollVoteUrl(PollenEntityId<Poll> pollId, String token) { + return getPollenUIUrlRenderService().getPollVoteUrl + (getUIContext().getPollVoteUrl(), + pollId.getReducedId(), + token); + } + } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java index 75ddd952..ab933ac4 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java @@ -142,6 +142,7 @@ public class VoteService extends PollenServiceSupport { commit(); getNotificationService().onVoteAdded(poll, result); + getFeedService().onVoteAdded(poll, result); return PollenEntityRef.of(result); @@ -163,6 +164,7 @@ public class VoteService extends PollenServiceSupport { commit(); getNotificationService().onVoteEdited(poll, result); + getFeedService().onVoteEdited(poll, result); return toBean(VoteBean.class, result); @@ -182,6 +184,7 @@ public class VoteService extends PollenServiceSupport { commit(); getNotificationService().onVoteDeleted(poll, vote); + getFeedService().onVoteDeleted(poll, vote); } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java index d8192600..b2809702 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/mail/EmailService.java @@ -138,10 +138,7 @@ public class EmailService extends PollenServiceSupport { email.setPollenUrl(getUIContext().getUiEndPoint()); - PollenEntityId<Poll> pollId = PollenEntityId.newId(Poll.class); - pollId.setEntityId(poll.getTopiaId()); - pollId.encode(serviceContext.getTopiaApplicationContext().getTopiaIdFactory()); - + PollenEntityId<Poll> pollId = getPollenEntityId(poll); email.setUrl(getPollenUIUrlRenderService().getPollEditUrl(getUIContext().getPollEditUrl(), pollId.getReducedId(), poll.getCreator().getPermission().getToken())); @@ -188,15 +185,7 @@ public class EmailService extends PollenServiceSupport { public PollInvitationEmail newPollInvitationEmail(Poll poll) { PollInvitationEmail email = new PollInvitationEmail(getLocale()); email.setPoll(poll); - - PollenEntityId<Poll> pollId = PollenEntityId.newId(Poll.class); - pollId.setEntityId(poll.getTopiaId()); - pollId.encode(serviceContext.getTopiaApplicationContext().getTopiaIdFactory()); - - email.setVoteUrl(getPollenUIUrlRenderService().getPollVoteUrl - (getUIContext().getPollVoteUrl(), - pollId.getReducedId(), - null)); + email.setVoteUrl(getPollVoteUrl(poll)); return email; } @@ -205,15 +194,7 @@ public class EmailService extends PollenServiceSupport { RestrictedPollInvitationEmail email = new RestrictedPollInvitationEmail(getLocale()); email.setPoll(poll); email.setPrincipal(principal); - - PollenEntityId<Poll> pollId = PollenEntityId.newId(Poll.class); - pollId.setEntityId(poll.getTopiaId()); - pollId.encode(serviceContext.getTopiaApplicationContext().getTopiaIdFactory()); - - email.setVoteUrl(getPollenUIUrlRenderService().getPollVoteUrl - (getUIContext().getPollVoteUrl(), - pollId.getReducedId(), - principal.getPermission().getToken())); + email.setVoteUrl(getPollVoteUrl(poll, principal.getPermission().getToken())); email.setToken(principal.getPermission().getToken()); @@ -226,10 +207,7 @@ public class EmailService extends PollenServiceSupport { email.setPollenUrl(pollenUIContext.getUiEndPoint()); - PollenEntityId<PollenUser> userId = PollenEntityId.newId(PollenUser.class); - userId.setEntityId(user.getTopiaId()); - userId.encode(serviceContext.getTopiaApplicationContext().getTopiaIdFactory()); - + PollenEntityId<PollenUser> userId = getPollenEntityId(user); email.setValidateUrl(getPollenUIUrlRenderService().getUserValidateUrl(pollenUIContext.getUserValidateUrl(), userId.getReducedId(), user.getEmailActivationToken().getToken())); @@ -242,10 +220,7 @@ public class EmailService extends PollenServiceSupport { email.setUser(user); email.setPollenUrl(pollenUIContext.getUiEndPoint()); - PollenEntityId<PollenUser> userId = PollenEntityId.newId(PollenUser.class); - userId.setEntityId(user.getTopiaId()); - userId.encode(serviceContext.getTopiaApplicationContext().getTopiaIdFactory()); - + PollenEntityId<PollenUser> userId = getPollenEntityId(user); email.setValidateUrl(getPollenUIUrlRenderService().getUserValidateUrl(pollenUIContext.getUserValidateUrl(), userId.getReducedId(), user.getEmailActivationToken().getToken())); diff --git a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties index 15c319c9..472f0ee8 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties @@ -102,6 +102,11 @@ pollen.error.voterList.member.weight.greaterThan0=member weight must be greater pollen.error.voterList.name.alreadyUsed=voterList name already used pollen.error.voterList.name.mandatory=voterList name can not be empty pollen.error.voterList.weight.greaterThan0=voterList weight must be greater than 0 +pollen.service.feed.pollCreated.description=On the %s, %s created the poll "%s". +pollen.service.feed.pollCreated.title=%s created the poll "%s" +pollen.service.feed.voteAdded.title=%s voted +pollen.service.feed.voteDeleted.title=%s deleted his vote +pollen.service.feed.voteEdited.title=%s edited his vote pollen.service.mail.ChoiceAddedEmail.subject=[Pollen] A choice was added in poll %s pollen.service.mail.ChoiceDeletedEmail.subject=[Pollen] A choice was deleted in poll %s pollen.service.mail.ChoiceEditedEmail.subject=[Pollen] A choice was edited in poll %s diff --git a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties index 58016941..3e8bc045 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties @@ -101,6 +101,11 @@ pollen.error.voterList.member.weight.greaterThan0=Le membre doit avoir un poid s pollen.error.voterList.name.alreadyUsed=Le nom de la liste de votant existe déjà pollen.error.voterList.name.mandatory=Nom de la liste de votant est obligatoire pollen.error.voterList.weight.greaterThan0=Poid de la liste de votant doit être supérieur à 0 +pollen.service.feed.pollCreated.description=Le %s, %s a créé le sondage %s. +pollen.service.feed.pollCreated.title=%s a créé le sondage "%s" +pollen.service.feed.voteAdded.title=%s a voté +pollen.service.feed.voteDeleted.title=%s a supprimé son vote +pollen.service.feed.voteEdited.title=%s a modifié son vote pollen.service.mail.ChoiceAddedEmail.subject=[Pollen] Un choix a été ajouté au sondage %s pollen.service.mail.ChoiceDeletedEmail.subject=[Pollen] Un choix a été supprimé du sondage %s pollen.service.mail.ChoiceEditedEmail.subject=[Pollen] Un choix a été modifié sur le sondage %s diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html index c354261c..144f1b74 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Poll.tag.html @@ -120,7 +120,8 @@ require("../popup/QrCodeButton.tag.html"); <h1> <QrCodeButton if={poll.pollType === "FREE"} value="{window.location.origin}{window.location.pathname}#poll/{poll.id}/vote"/> {poll.title} - <h1> + <a href="{session.configuration.endPoint}/v1/polls/{poll.id}/feed" class="fa fa-rss-square" aria-hidden="true"></a> + </h1> <h3>{poll.description}</h3> diff --git a/pom.xml b/pom.xml index 603652d7..f7b20abc 100644 --- a/pom.xml +++ b/pom.xml @@ -470,11 +470,11 @@ <!-- Rome (rss) --> - <!--dependency> - <groupId>rome</groupId> + <dependency> + <groupId>com.rometools</groupId> <artifactId>rome</artifactId> - <version>1.0</version> - </dependency--> + <version>1.7.2</version> + </dependency> <!-- Logging --> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.