From c48e865a6584a533477aa7dbe350e9cf21b31c18 Mon Sep 17 00:00:00 2001 From: Christoph Thelen <christoph.thelen@mni.thm.de> Date: Wed, 12 Nov 2014 17:15:42 +0100 Subject: [PATCH] Cleaner use of interposed entity with additional web socket support --- .../AudienceQuestionController.java | 13 ++-- .../java/de/thm/arsnova/dao/CouchDBDao.java | 6 +- .../transport/InterposedQuestion.java | 71 +++++++++++++++++++ .../events/DeleteInterposedQuestionEvent.java | 26 +++++++ .../arsnova/services/IQuestionService.java | 2 + .../thm/arsnova/services/QuestionService.java | 16 ++++- .../arsnova/socket/ARSnovaSocketIOServer.java | 14 ++++ 7 files changed, 135 insertions(+), 13 deletions(-) create mode 100644 src/main/java/de/thm/arsnova/entities/transport/InterposedQuestion.java create mode 100644 src/main/java/de/thm/arsnova/events/DeleteInterposedQuestionEvent.java diff --git a/src/main/java/de/thm/arsnova/controller/AudienceQuestionController.java b/src/main/java/de/thm/arsnova/controller/AudienceQuestionController.java index 3f42d627e..a674b6b24 100644 --- a/src/main/java/de/thm/arsnova/controller/AudienceQuestionController.java +++ b/src/main/java/de/thm/arsnova/controller/AudienceQuestionController.java @@ -32,10 +32,9 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import de.thm.arsnova.entities.InterposedQuestion; +import de.thm.arsnova.entities.transport.InterposedQuestion; import de.thm.arsnova.entities.InterposedReadingCount; import de.thm.arsnova.exceptions.BadRequestException; -import de.thm.arsnova.exceptions.PreconditionFailedException; import de.thm.arsnova.services.IQuestionService; import de.thm.arsnova.web.DeprecatedApi; @@ -62,24 +61,20 @@ public class AudienceQuestionController extends AbstractController { @RequestMapping(value = "/", method = RequestMethod.GET) public final List<InterposedQuestion> getInterposedQuestions(@RequestParam final String sessionkey) { - return questionService.getInterposedQuestions(sessionkey); + return InterposedQuestion.fromList(questionService.getInterposedQuestions(sessionkey)); } @RequestMapping(value = "/{questionId}", method = RequestMethod.GET) public final InterposedQuestion getInterposedQuestion(@PathVariable final String questionId) { - return questionService.readInterposedQuestion(questionId); + return new InterposedQuestion(questionService.readInterposedQuestion(questionId)); } @RequestMapping(value = "/", method = RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) public final void postInterposedQuestion( @RequestParam final String sessionkey, - @RequestBody final InterposedQuestion question + @RequestBody final de.thm.arsnova.entities.InterposedQuestion question ) { - if (!sessionkey.equals(question.getSessionId())) { - throw new PreconditionFailedException(); - } - if (questionService.saveQuestion(question)) { return; } diff --git a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java index cdc03e8cf..2f43cad0b 100644 --- a/src/main/java/de/thm/arsnova/dao/CouchDBDao.java +++ b/src/main/java/de/thm/arsnova/dao/CouchDBDao.java @@ -424,7 +424,7 @@ public class CouchDBDao implements IDatabaseDao { q.put("gridType", question.getGridType()); q.put("scaleFactor", question.getScaleFactor()); q.put("gridScaleFactor", question.getGridScaleFactor()); - + return q; } @@ -463,7 +463,7 @@ public class CouchDBDao implements IDatabaseDao { q.put("gridType", question.getGridType()); q.put("scaleFactor", question.getScaleFactor()); q.put("gridScaleFactor", question.getGridScaleFactor()); - + database.saveDocument(q); question.set_rev(q.getRev()); @@ -876,7 +876,7 @@ public class CouchDBDao implements IDatabaseDao { @Override public List<InterposedQuestion> getInterposedQuestions(final Session session) { - final NovaView view = new NovaView("interposed_question/by_session"); + final NovaView view = new NovaView("interposed_question/by_session_full"); view.setKey(session.get_id()); final ViewResults questions = getDatabase().view(view); if (questions == null || questions.isEmpty()) { diff --git a/src/main/java/de/thm/arsnova/entities/transport/InterposedQuestion.java b/src/main/java/de/thm/arsnova/entities/transport/InterposedQuestion.java new file mode 100644 index 000000000..702836ccc --- /dev/null +++ b/src/main/java/de/thm/arsnova/entities/transport/InterposedQuestion.java @@ -0,0 +1,71 @@ +package de.thm.arsnova.entities.transport; + +import java.util.ArrayList; +import java.util.List; + +public class InterposedQuestion { + + private String id; + private String subject; + private String text; + private long timestamp; + private boolean read; + + public static List<InterposedQuestion> fromList(List<de.thm.arsnova.entities.InterposedQuestion> questions) { + ArrayList<InterposedQuestion> interposedQuestions = new ArrayList<InterposedQuestion>(); + for (de.thm.arsnova.entities.InterposedQuestion question : questions) { + interposedQuestions.add(new InterposedQuestion(question)); + } + return interposedQuestions; + } + + public InterposedQuestion(de.thm.arsnova.entities.InterposedQuestion question) { + this.id = question.get_id(); + this.subject = question.getSubject(); + this.text = question.getText(); + this.timestamp = question.getTimestamp(); + this.read = question.isRead(); + } + + public InterposedQuestion() {} + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public boolean isRead() { + return read; + } + + public void setRead(boolean read) { + this.read = read; + } +} diff --git a/src/main/java/de/thm/arsnova/events/DeleteInterposedQuestionEvent.java b/src/main/java/de/thm/arsnova/events/DeleteInterposedQuestionEvent.java new file mode 100644 index 000000000..b8aea746a --- /dev/null +++ b/src/main/java/de/thm/arsnova/events/DeleteInterposedQuestionEvent.java @@ -0,0 +1,26 @@ +package de.thm.arsnova.events; + +import de.thm.arsnova.entities.InterposedQuestion; +import de.thm.arsnova.entities.Session; + +public class DeleteInterposedQuestionEvent extends NovaEvent { + + private static final long serialVersionUID = 1L; + + private final Session session; + + private final InterposedQuestion question; + + public DeleteInterposedQuestionEvent(Object source, Session session, InterposedQuestion question) { + super(source); + this.session = session; + this.question = question; + } + + @Override + public void accept(NovaEventVisitor visitor) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/de/thm/arsnova/services/IQuestionService.java b/src/main/java/de/thm/arsnova/services/IQuestionService.java index 4b1746d1f..a964c77e3 100644 --- a/src/main/java/de/thm/arsnova/services/IQuestionService.java +++ b/src/main/java/de/thm/arsnova/services/IQuestionService.java @@ -66,6 +66,8 @@ public interface IQuestionService { InterposedQuestion readInterposedQuestion(String questionId); + InterposedQuestion readInterposedQuestionInternal(String questionId, User user); + Question update(Question question); void deleteAnswers(String questionId); diff --git a/src/main/java/de/thm/arsnova/services/QuestionService.java b/src/main/java/de/thm/arsnova/services/QuestionService.java index 0607ac273..2224949f8 100644 --- a/src/main/java/de/thm/arsnova/services/QuestionService.java +++ b/src/main/java/de/thm/arsnova/services/QuestionService.java @@ -42,6 +42,7 @@ import de.thm.arsnova.entities.Question; import de.thm.arsnova.entities.Session; import de.thm.arsnova.entities.User; import de.thm.arsnova.events.DeleteAnswerEvent; +import de.thm.arsnova.events.DeleteInterposedQuestionEvent; import de.thm.arsnova.events.NewAnswerEvent; import de.thm.arsnova.events.NewInterposedQuestionEvent; import de.thm.arsnova.events.NewQuestionEvent; @@ -191,6 +192,10 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis throw new NotFoundException(); } databaseDao.deleteInterposedQuestion(question); + + final Session session = databaseDao.getSessionFromKeyword(question.getSessionId()); + final DeleteInterposedQuestionEvent event = new DeleteInterposedQuestionEvent(this, session, question); + this.publisher.publishEvent(event); } @Override @@ -358,13 +363,22 @@ public class QuestionService implements IQuestionService, ApplicationEventPublis @Override @PreAuthorize("isAuthenticated()") public InterposedQuestion readInterposedQuestion(final String questionId) { + final User user = userService.getCurrentUser(); + return this.readInterposedQuestionInternal(questionId, user); + } + + /* + * The "internal" suffix means it is called by internal services that have no authentication! + * TODO: Find a better way of doing this... + */ + @Override + public InterposedQuestion readInterposedQuestionInternal(final String questionId, User user) { final InterposedQuestion question = databaseDao.getInterposedQuestion(questionId); if (question == null) { throw new NotFoundException(); } final Session session = databaseDao.getSessionFromKeyword(question.getSessionId()); - final User user = userService.getCurrentUser(); if (session.isCreator(user)) { databaseDao.markInterposedQuestionAsRead(question); } diff --git a/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java b/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java index 254ddbc9a..4f20db3ed 100644 --- a/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java +++ b/src/main/java/de/thm/arsnova/socket/ARSnovaSocketIOServer.java @@ -151,6 +151,20 @@ public class ARSnovaSocketIOServer implements ApplicationListener<NovaEvent>, No } }); + server.addEventListener( + "readInterposedQuestion", + de.thm.arsnova.entities.transport.InterposedQuestion.class, + new DataListener<de.thm.arsnova.entities.transport.InterposedQuestion>() { + @Override + public void onData( + SocketIOClient client, + de.thm.arsnova.entities.transport.InterposedQuestion question, + AckRequest ackRequest) { + final User user = userService.getUser2SocketId(client.getSessionId()); + questionService.readInterposedQuestionInternal(question.getId(), user); + } + }); + server.addConnectListener(new ConnectListener() { @Override public void onConnect(final SocketIOClient client) { } -- GitLab