SilverpeasQuestionManager.java
/*
* Copyright (C) 2000 - 2024 Silverpeas
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* As a special exception to the terms and conditions of version 3.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* Open Source Software ("FLOSS") applications as described in Silverpeas's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* "http://www.silverpeas.org/docs/core/legal/floss_exception.html"
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.silverpeas.components.questionreply.service;
import org.silverpeas.components.questionreply.QuestionReplyException;
import org.silverpeas.components.questionreply.index.QuestionIndexer;
import org.silverpeas.components.questionreply.model.Question;
import org.silverpeas.components.questionreply.model.Recipient;
import org.silverpeas.components.questionreply.model.Reply;
import org.silverpeas.components.questionreply.service.notification.SubscriptionNotifier;
import org.silverpeas.core.ResourceReference;
import org.silverpeas.core.WAPrimaryKey;
import org.silverpeas.core.admin.service.OrganizationController;
import org.silverpeas.core.admin.user.model.User;
import org.silverpeas.core.annotation.Service;
import org.silverpeas.core.contribution.content.wysiwyg.service.WysiwygController;
import org.silverpeas.core.contribution.contentcontainer.content.ContentManagerException;
import org.silverpeas.core.i18n.I18NHelper;
import org.silverpeas.core.persistence.jdbc.DBUtil;
import org.silverpeas.core.persistence.jdbc.bean.*;
import org.silverpeas.kernel.util.StringUtil;
import org.silverpeas.kernel.logging.SilverLogger;
import javax.inject.Inject;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.silverpeas.core.notification.user.builder.helper.UserNotificationHelper.buildAndSend;
import static org.silverpeas.core.persistence.jdbc.bean.BeanCriteria.OPERATOR.GREATER;
import static org.silverpeas.core.persistence.jdbc.bean.BeanCriteria.OPERATOR.NOT_EQUALS;
@Service
@SuppressWarnings("deprecation")
public class SilverpeasQuestionManager implements QuestionManager {
private static final String STATUS = "status";
private static final String INSTANCE_ID = "instanceId";
private static final String QUESTION_ID = "questionId";
@Inject
private QuestionIndexer questionIndexer;
private SilverpeasBeanDAO<Question> questionDao = null;
private SilverpeasBeanDAO<Reply> replyDao = null;
private SilverpeasBeanDAO<Recipient> recipientDao = null;
@Inject
private QuestionReplyContentManager contentManager;
@Inject
private OrganizationController controller;
SilverpeasQuestionManager() {
try {
questionDao = SilverpeasBeanDAOFactory.getDAO(Question.class);
replyDao = SilverpeasBeanDAOFactory.getDAO(Reply.class);
recipientDao = SilverpeasBeanDAOFactory.getDAO(Recipient.class);
} catch (PersistenceException ex) {
SilverLogger.getLogger(this).error(ex);
}
}
/**
* Create and persist a question with targeted recipient (be careful recipient doesn't have
* question identifier set)
* @param question the question to create
* @return the generated question identifier
* @throws QuestionReplyException if an error occurs
*/
@Override
public long createQuestion(Question question) throws QuestionReplyException {
try (Connection con = DBUtil.openConnection()) {
Collection<Recipient> recipients = question.readRecipients();
IdPK pkQ = (IdPK) questionDao.add(con, question);
question.setPK(pkQ);
questionIndexer.createIndex(question, Collections.emptyList());
long idQ = pkQ.getIdAsLong();
if (recipients != null) {
for (Recipient recipient : recipients) {
recipient.setQuestionId(idQ);
createRecipient(con, recipient);
}
}
question.setPK(pkQ);
contentManager.createSilverContent(con, question);
return idQ;
} catch (SQLException | ContentManagerException | PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* enregistre une réponse à une question => met à jour publicReplyNumber et/ou privateReplyNumber
* et replyNumber de la question ainsi que le status à 1
*/
@Override
public long createReply(Reply reply, Question question) throws QuestionReplyException {
try (Connection con = DBUtil.openConnection()) {
IdPK pkR = (IdPK) replyDao.add(con, reply);
WysiwygController.createFileAndAttachment(reply.readCurrentWysiwygContent(),
new ResourceReference(pkR), reply.getCreatorId(), I18NHelper.DEFAULT_LANGUAGE);
long idR = pkR.getIdAsLong();
if (question.hasNewStatus()) {
question.waitForAnswer();
}
updateQuestion(con, question);
questionIndexer.updateIndex(question, getAllReplies(reply.getQuestionId(), question.
getInstanceId()));
notifySubscribers(question, reply);
return idR;
} catch (SQLException | PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* enregistre un destinataire
*/
private void createRecipient(Connection con, Recipient recipient) throws QuestionReplyException {
try {
recipientDao.add(con, recipient);
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* supprime tous les destinataires d'une question
*/
private void deleteRecipients(Connection con, long questionId) throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion(QUESTION_ID, questionId);
recipientDao.removeBy(con, criteria);
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* Clos une liste de questions : updateQuestion
*/
@Override
public void closeQuestions(Collection<Long> questionIds) throws QuestionReplyException {
if (questionIds != null) {
try (Connection con = DBUtil.openConnection()) {
for (Long idQ : questionIds) {
Question question = getQuestion(idQ);
question.close();
updateQuestion(con, question);
}
} catch (SQLException e) {
throw new QuestionReplyException(e);
}
}
}
@Override
public void openQuestions(Collection<Long> questionIds) throws QuestionReplyException {
if (questionIds != null) {
try (Connection con = DBUtil.openConnection()) {
for (Long idQ : questionIds) {
Question question = getQuestion(idQ);
question.waitForAnswer();
updateQuestion(con, question);
}
} catch (SQLException e) {
throw new QuestionReplyException(e);
}
}
}
/*
* Modifie les destinataires d'une question : deleteRecipients, createRecipient
*/
@Override
public void updateQuestionRecipients(Question question) throws QuestionReplyException {
try (Connection con = DBUtil.openConnection()) {
Collection<Recipient> recipients = question.readRecipients();
deleteRecipients(con, ((IdPK) question.getPK()).getIdAsLong());
if (recipients != null) {
for (Recipient recipient : recipients) {
recipient.setQuestionId(((IdPK) question.getPK()).getIdAsLong());
createRecipient(con, recipient);
}
}
} catch (SQLException | QuestionReplyException e) {
throw new QuestionReplyException(e);
}
}
/*
* Affecte le status public à 0 de toutes les réponses d'une liste de questions : updateReply
* Affecte le nombre de réponses publiques de la question à 0 : updateQuestion si question en
* attente, on a demandé à la supprimer : deleteQuestion
*/
@Override
public void updateQuestionRepliesPublicStatus(Collection<Long> questionIds)
throws QuestionReplyException {
try (Connection con = DBUtil.openConnection()) {
if (questionIds != null) {
for (Long idQ : questionIds) {
Question question = getQuestion(idQ);
Collection<Reply> replies = getQuestionPublicReplies(idQ, question.getInstanceId());
if (replies != null) {
for (Reply reply : replies) {
reply.setPublicReply(0);
addComponentId(reply, question.getPK().getInstanceId());
updateReply(con, reply);
}
updateQuestion(con, question);
}
if (question.hasNewStatus()) {
deleteQuestion(con, idQ);
}
}
}
} catch (SQLException | QuestionReplyException e) {
throw new QuestionReplyException(e);
}
}
/*
* Affecte le status private à 0 de toutes les réponses d'une liste de questions : updateReply
* Affecte le nombre de réponses privées de la question à 0 : updateQuestion
*/
@Override
public void updateQuestionRepliesPrivateStatus(Collection<Long> questionIds)
throws QuestionReplyException {
try (Connection con = DBUtil.openConnection()) {
if (questionIds != null) {
for (Long idQ : questionIds) {
Question question = getQuestion(idQ);
Collection<Reply> replies = getQuestionPrivateReplies(idQ, question.getInstanceId());
if (replies != null) {
for (Reply reply : replies) {
reply.setPrivateReply(0);
addComponentId(reply, question.getPK().getInstanceId());
updateReply(con, reply);
}
updateQuestion(con, question);
}
}
}
} catch (SQLException | QuestionReplyException e) {
throw new QuestionReplyException(e);
}
}
private void addComponentId(Reply reply, String componentId) {
reply.getPK().setComponentName(componentId);
}
/*
* Affecte le status public à 0 d'une liste de réponses : updateReply Décremente le nombre de
* réponses publiques de la question d'autant : updateQuestion
*/
@Override
public void updateRepliesPublicStatus(Collection<Long> replyIds, Question question)
throws QuestionReplyException {
try (Connection con = DBUtil.openConnection()) {
if (replyIds != null) {
for (Long idR : replyIds) {
Reply reply = getReply(idR);
if (reply != null) {
reply.setPublicReply(0);
addComponentId(reply, question.getPK().getInstanceId());
updateReply(con, reply);
}
}
updateQuestion(con, question);
}
} catch (SQLException | QuestionReplyException e) {
throw new QuestionReplyException(e);
}
}
/*
* Affecte le status private à 0 d'une liste de réponses : updateReply Décremente le nombre de
* réponses privées de la question d'autant : updateQuestion
*/
@Override
public void updateRepliesPrivateStatus(Collection<Long> replyIds, Question question)
throws QuestionReplyException {
try (Connection con = DBUtil.openConnection()) {
if (replyIds != null) {
for (Long idR : replyIds) {
Reply reply = getReply(idR);
if (reply != null) {
reply.setPrivateReply(0);
addComponentId(reply, question.getPK().getInstanceId());
updateReply(con, reply);
}
}
updateQuestion(con, question);
}
} catch (SQLException | QuestionReplyException e) {
throw new QuestionReplyException(e);
}
}
/*
* Modifie une question => la question est supprimée si publicReplyNumber et privateReplyNumber
* sont à 0 et que la question est close => met à jour publicReplyNumber et/ou privateReplyNumber
* et replyNumber de la question
*/
private void updateQuestion(Connection con, Question question) throws QuestionReplyException {
try {
long idQ = ((IdPK) question.getPK()).getIdAsLong();
question.setReplyNumber(getQuestionRepliesNumber(idQ));
question.setPublicReplyNumber(getQuestionPublicRepliesNumber(idQ));
question.setPrivateReplyNumber(getQuestionPrivateRepliesNumber(idQ));
if ((question.getReplyNumber() == 0) && question.hasClosedStatus()) {
deleteQuestion(con, idQ);
} else {
questionDao.update(con, question);
questionIndexer.updateIndex(question, getAllReplies(idQ, question.getInstanceId()));
question.getPK().setComponentName(question.getInstanceId());
contentManager.updateSilverContentVisibility(question);
}
} catch (Exception e) {
throw new QuestionReplyException(e);
}
}
/*
* Modifie une question => la question est supprimée si publicReplyNumber et privateReplyNumber
* sont à 0 et que la question est close => met à jour publicReplyNumber et/ou privateReplyNumber
* et replyNumber de la question
*/
@Override
public void updateQuestion(Question question) throws QuestionReplyException {
try {
long idQ = ((IdPK) question.getPK()).getIdAsLong();
question.setReplyNumber(getQuestionRepliesNumber(idQ));
question.setPublicReplyNumber(getQuestionPublicRepliesNumber(idQ));
question.setPrivateReplyNumber(getQuestionPrivateRepliesNumber(idQ));
if ((question.getReplyNumber() == 0) && question.hasClosedStatus()) {
deleteQuestion(idQ);
} else {
questionDao.update(question);
questionIndexer.updateIndex(question, getAllReplies(idQ, question.getInstanceId()));
question.getPK().setComponentName(question.getInstanceId());
contentManager.updateSilverContentVisibility(question);
}
} catch (Exception e) {
throw new QuestionReplyException(e);
}
}
/*
* Modifie une réponse => La réponse est supprimée si le status public et le status private sont à
* 0
*/
private void updateReply(Connection con, Reply reply) throws QuestionReplyException {
try {
Question question = getQuestion(reply.getQuestionId());
reply.getPK().setComponentName(question.getInstanceId());
if ((reply.getPublicReply() == 0) && (reply.getPrivateReply() == 0)) {
deleteReply(con, reply.getPK());
} else {
replyDao.update(con, reply);
updateWysiwygContent(reply);
}
questionIndexer.updateIndex(question, getAllReplies(reply.getQuestionId(), question.
getInstanceId()));
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* Modifie une réponse => La réponse est supprimée si le status public et le status private sont à
* 0
*/
@Override
public void updateReply(Reply reply) throws QuestionReplyException {
try {
Question question = getQuestion(reply.getQuestionId());
if ((reply.getPublicReply() == 0) && (reply.getPrivateReply() == 0)) {
deleteReply(((IdPK) reply.getPK()).getIdAsLong());
} else {
replyDao.update(reply);
updateReplyWysiwygContent(reply);
}
questionIndexer.updateIndex(question, getAllReplies(reply.getQuestionId(), question.
getInstanceId()));
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
private void updateReplyWysiwygContent(final Reply reply) {
updateWysiwygContent(reply);
}
private void deleteQuestion(Connection con, long questionId) throws QuestionReplyException {
try {
deleteRecipients(con, questionId);
IdPK pk = new IdPK();
pk.setIdAsLong(questionId);
Question question = getQuestion(questionId);
String peasId = question.getInstanceId();
questionDao.remove(con, pk);
questionIndexer.deleteIndex(question);
pk.setComponentName(peasId);
contentManager.deleteSilverContent(con, pk);
} catch (Exception e) {
throw new QuestionReplyException(e);
}
}
private void deleteQuestion(long questionId) throws QuestionReplyException {
try(Connection connection = DBUtil.openConnection()) {
deleteQuestion(connection, questionId);
} catch (SQLException e) {
throw new QuestionReplyException(e);
}
}
@Override
public void deleteQuestionAndReplies(Collection<Long> questionIds) throws QuestionReplyException {
// pour chaque question
for (Long questionId : questionIds) {
Connection con = null;
try {
con = DBUtil.openConnection();
deleteRecipients(con, questionId);
IdPK pk = new IdPK();
pk.setIdAsLong(questionId);
Question question = getQuestion(questionId);
String peasId = question.getInstanceId();
// rechercher les réponses
Collection<Reply> replies = getAllReplies(questionId, peasId);
for (Reply reply : replies) {
long replyId = Long.parseLong(reply.getPK().getId());
addComponentId(reply, question.getInstanceId());
// supprimer la réponse et son index
deleteReply(replyId);
}
questionIndexer.deleteIndex(question);
// supprimer la question
questionDao.remove(con, pk);
pk.setComponentName(peasId);
contentManager.deleteSilverContent(con, pk);
} catch (Exception e) {
throw new QuestionReplyException(e);
} finally {
DBUtil.close(con);
}
}
}
@Override
public List<Reply> getAllReplies(long questionId, String instanceId)
throws QuestionReplyException {
List<Reply> allReplies = new ArrayList<>();
try {
Collection<Reply> privateReplies = getQuestionPrivateReplies(questionId, instanceId);
allReplies.addAll(privateReplies);
Collection<Reply> publicReplies = getQuestionPublicReplies(questionId, instanceId);
allReplies.addAll(publicReplies);
return allReplies;
} catch (Exception e) {
throw new QuestionReplyException(e);
}
}
/*
* supprime une réponse
*/
private void deleteReply(long replyId) throws QuestionReplyException {
try (Connection con = DBUtil.openConnection()) {
IdPK pk = new IdPK();
pk.setIdAsLong(replyId);
replyDao.remove(con, pk);
} catch (SQLException | PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* supprime une réponse
*/
private void deleteReply(Connection con, WAPrimaryKey replyId) throws QuestionReplyException {
try {
replyDao.remove(con, replyId);
WysiwygController
.deleteFile(replyId.getInstanceId(), replyId.getId(), I18NHelper.DEFAULT_LANGUAGE);
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* recupère une question
*/
@Override
public Question getQuestion(long questionId) throws QuestionReplyException {
try {
IdPK pk = new IdPK();
pk.setIdAsLong(questionId);
return questionDao.findByPrimaryKey(pk);
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
@Override
public Question getQuestionAndReplies(long questionId) throws QuestionReplyException {
try {
IdPK pk = new IdPK();
pk.setIdAsLong(questionId);
Question question = questionDao.findByPrimaryKey(pk);
Collection<Reply> replies = getQuestionReplies(questionId, question.getInstanceId());
question.writeReplies(replies);
return question;
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
@Override
public List<Question> getQuestionsByIds(List<String> ids) throws QuestionReplyException {
BeanCriteria criteria = ids.isEmpty() ? BeanCriteria.emptyCriteria() :
BeanCriteria.addCriterion("id",
ids.stream().map(Integer::parseInt).collect(Collectors.toSet()));
try {
return new ArrayList<>(questionDao.findBy(criteria));
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* recupère la liste des réponses d'une question
*/
@Override
public List<Reply> getQuestionReplies(long questionId, String instanceId)
throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion(QUESTION_ID, questionId);
List<Reply> replies = new ArrayList<>(
replyDao.findBy(criteria));
for (Reply reply : replies) {
reply.getPK().setComponentName(instanceId);
reply.loadWysiwygContent();
}
return replies;
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* recupère la liste des réponses publiques d'une question
*/
@Override
public List<Reply> getQuestionPublicReplies(long questionId, String instanceId)
throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion("publicReply", 1)
.and(QUESTION_ID, questionId);
List<Reply> replies = new ArrayList<>(replyDao.findBy(criteria));
for (Reply reply : replies) {
reply.getPK().setComponentName(instanceId);
reply.loadWysiwygContent();
}
return replies;
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* recupère la liste des réponses privées d'une question
*/
@Override
public List<Reply> getQuestionPrivateReplies(long questionId, String instanceId)
throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion("privateReply", 1)
.and(QUESTION_ID, questionId);
List<Reply> replies = new ArrayList<>(replyDao.findBy(criteria));
for (Reply reply : replies) {
reply.getPK().setComponentName(instanceId);
reply.loadWysiwygContent();
}
return replies;
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* recupère la liste des destinataires d'une question
*/
@Override
public List<Recipient> getQuestionRecipients(long questionId) throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion(QUESTION_ID, questionId);
return new ArrayList<>(recipientDao.findBy(criteria));
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* recupère une réponse
*/
@Override
public Reply getReply(long replyId) throws QuestionReplyException {
try {
IdPK pk = new IdPK();
pk.setIdAsLong(replyId);
Reply reply = replyDao.findByPrimaryKey(pk);
if (reply != null) {
reply.loadWysiwygContent();
}
return reply;
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* Recupère la liste des questions emises par un utilisateur => Q dont il est l'auteur qui ne sont
* pas closes ou closes avec réponses privées
*/
@Override
public List<Question> getSendQuestions(String userId, String instanceId)
throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion(INSTANCE_ID, instanceId)
.and("creatorId", Integer.parseInt(userId))
.and(BeanCriteria.addCriterion(STATUS, NOT_EQUALS, 2)
.or("privateReplyNumber", GREATER, 0));
return new ArrayList<>(questionDao.findBy(criteria));
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* Recupère la liste des questions recues par un utilisateur => Q dont il est le destinataire et
* qui ne sont pas closes
*/
@Override
public List<Question> getReceiveQuestions(String userId, String instanceId)
throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion(INSTANCE_ID, instanceId)
.and(STATUS, NOT_EQUALS, 2)
.andSubQuery("id", BeanCriteria.OPERATOR.IN,
"questionId from SC_QuestionReply_Recipient",
BeanCriteria.addCriterion("userId", Integer.parseInt(userId)));
return new ArrayList<>(questionDao.findBy(criteria));
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* Recupère la liste des questions qui ne sont pas closes ou closes avec réponses publiques
*/
@Override
public List<Question> getQuestions(String instanceId) throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion(INSTANCE_ID, instanceId)
.and(BeanCriteria.addCriterion(STATUS, NOT_EQUALS, 2)
.or("privateReplyNumber", GREATER, 0));
criteria.setDescOrderBy("creationDate", "id");
return new ArrayList<>(questionDao.findBy(criteria));
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* Recupère la liste de toutes les questions avec toutes ses réponses
*/
@Override
public List<Question> getAllQuestions(String instanceId) throws QuestionReplyException {
List<Question> allQuestions = getQuestions(instanceId);
List<Question> questions = new ArrayList<>(allQuestions.size());
for (Question question : allQuestions) {
Question fullQuestion = getQuestionAndReplies(Long.parseLong(question.getPK().getId()));
questions.add(fullQuestion);
}
if (isSortable(instanceId)) {
questions.sort(QuestionRegexpComparator.getInstance());
}
return questions;
}
@Override
public List<Question> getAllQuestionsByCategory(String instanceId, String categoryId)
throws QuestionReplyException {
List<Question> allQuestions = getQuestions(instanceId);
List<Question> questions = new ArrayList<>(allQuestions.size());
for (Question question : allQuestions) {
if ((StringUtil.isNotDefined(question.getCategoryId()) &&
StringUtil.isNotDefined(categoryId)) ||
(StringUtil.isDefined(categoryId) && StringUtil.isDefined(question.getCategoryId()) &&
question.getCategoryId().equals(categoryId))) {
// la question est sans catégorie
Question fullQuestion = getQuestionAndReplies(Long.parseLong(question.getPK().getId()));
questions.add(fullQuestion);
}
}
if (isSortable(instanceId)) {
questions.sort(QuestionRegexpComparator.getInstance());
}
return questions;
}
/*
* Recupère la liste des questions publiques avec réponses
*/
@Override
public List<Question> getPublicQuestions(String instanceId) throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion(INSTANCE_ID, instanceId)
.and("publicReplyNumber", GREATER, 0);
criteria.setAscOrderBy("id");
return new ArrayList<>(questionDao.findBy(criteria));
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/**
* Save and persist question and reply given in parameter
* @param question the new question
* @param reply the answer linked to the given question
* @return the created question identifier
* @throws QuestionReplyException if an error occurs
*/
@Override
public long createQuestionReply(Question question, Reply reply) throws QuestionReplyException {
Connection con = null;
long idQ;
try {
con = DBUtil.openConnection();
IdPK pkQ = (IdPK) questionDao.add(con, question);
idQ = pkQ.getIdAsLong();
reply.setQuestionId(idQ);
WAPrimaryKey pkR = replyDao.add(con, reply);
reply.getPK().setId(pkR.getId());
WysiwygController.createFileAndAttachment(reply.readCurrentWysiwygContent(),
new ResourceReference(pkR), reply.getCreatorId(), I18NHelper.DEFAULT_LANGUAGE);
questionIndexer.createIndex(question, Collections.singletonList(reply));
Question updatedQuestion = getQuestion(idQ);
contentManager.createSilverContent(con, updatedQuestion);
notifySubscribers(question, reply);
} catch (Exception e) {
throw new QuestionReplyException(e);
} finally {
DBUtil.close(con);
}
return idQ;
}
/*
* recupère le nombre de réponses d'une question
*/
private int getQuestionRepliesNumber(long questionId) throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion(QUESTION_ID, questionId);
Collection<Reply> replies = replyDao.findBy(criteria);
return replies.size();
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* recupère le nombre de réponses publiques d'une question
*/
private int getQuestionPublicRepliesNumber(long questionId) throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion("publicReply", 1)
.and(QUESTION_ID, questionId);
Collection<Reply> replies =
replyDao.findBy(criteria);
return replies.size();
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
/*
* recupère le nombre de réponses privées d'une question
*/
private int getQuestionPrivateRepliesNumber(long questionId) throws QuestionReplyException {
try {
BeanCriteria criteria = BeanCriteria.addCriterion("privateReply", 1)
.and(QUESTION_ID, questionId);
Collection<Reply> replies = replyDao.findBy(criteria);
return replies.size();
} catch (PersistenceException e) {
throw new QuestionReplyException(e);
}
}
protected void updateWysiwygContent(Reply reply) {
if (WysiwygController.haveGotWysiwyg(reply.getPK().getInstanceId(), reply.getPK().getId(),
I18NHelper.DEFAULT_LANGUAGE)) {
WysiwygController
.updateFileAndAttachment(reply.readCurrentWysiwygContent(), reply.getPK().getInstanceId(),
reply.getPK().getId(), reply.getCreatorId(), I18NHelper.DEFAULT_LANGUAGE);
} else {
WysiwygController.createUnindexedFileAndAttachment(reply.readCurrentWysiwygContent(),
new ResourceReference(reply.getPK()),
reply.getCreatorId(), I18NHelper.DEFAULT_LANGUAGE);
}
}
protected boolean isSortable(String instanceId) {
return StringUtil
.getBooleanValue(controller.getComponentParameterValue(instanceId, "sortable"));
}
private void notifySubscribers(Question question, Reply reply) {
if (reply.getPublicReply() == 1) {
final User sender = reply.readAuthor();
buildAndSend(new SubscriptionNotifier(sender, question, reply));
}
}
}