package com.QA; import com.QA.rank.Hit; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Index; import org.hibernate.annotations.Type; import org.hibernate.search.annotations.DocumentId; import org.hibernate.search.annotations.FieldBridge; import org.hibernate.search.bridge.builtin.IntegerBridge; import org.jblooming.ontology.SecuredLoggableSupport; import org.jblooming.operator.User; import org.jblooming.oql.OqlQuery; import org.jblooming.persistence.PersistenceHome; import org.jblooming.persistence.exceptions.FindByPrimaryKeyException; import org.jblooming.persistence.exceptions.FindException; import org.jblooming.persistence.exceptions.StoreException; import org.jblooming.utilities.JSP; import org.jblooming.waf.settings.ApplicationState; import org.jblooming.waf.settings.I18n; import javax.persistence.*; import java.io.Serializable; import java.util.*; @Entity @Table(name = "qa_answer") public class Answer extends SecuredLoggableSupport { private Question question; private String text; private int finalOrder = 0; private QAOperator owner; private boolean deleted = false; private boolean accepted = false; private String contentRating; private Set<Upvote> upvotes = new HashSet(); // inverse private List<Comment> comments = new ArrayList(); // inverse private List<AnswerRevision> answerRevision = new ArrayList(); // inverse //denormalized social weight private double totUpvotesAndAcceptance; @Id @Type(type = "int") @GeneratedValue(strategy = GenerationType.AUTO) @DocumentId @FieldBridge(impl = IntegerBridge.class) public Serializable getId() { return super.getId(); } public boolean isDeleted() { return deleted; } public void setDeleted(boolean deleted) { this.deleted = deleted; } @ManyToOne(targetEntity = Question.class) @ForeignKey(name = "fk_prop_man") @Index(name = "idx_prop_man") public Question getQuestion() { return question; } public void setQuestion(Question question) { this.question = question; } @Lob public String getText() { return text; } public void setText(String text) { this.text = text; } @OneToMany(targetEntity = Upvote.class) @JoinColumn(name = "answer") @OrderBy("operator") public Set<Upvote> getUpvotes() { return upvotes; } private void setUpvotes(Set<Upvote> upvotes) { this.upvotes = upvotes; } @OneToMany(targetEntity = Comment.class) @JoinColumn(name = "answer") //@OrderBy("parent") public List<Comment> getComments() { return comments; } private void setComments(List<Comment> cts) { this.comments= cts; } @ManyToOne(targetEntity = QAOperator.class) @ForeignKey(name = "fk_answ_own") @Index(name = "idx_answ_own") @JoinColumn(name = "ownerx") public QAOperator getOwner() { return owner; } public void setOwner(QAOperator owner) { this.owner = owner; } protected boolean isAccepted() { return accepted; } private void setAccepted(boolean accepted) { this.accepted = accepted; } public int getFinalOrder() { return finalOrder; } public void setFinalOrder(int finalOrder) { this.finalOrder = finalOrder; } @OneToMany(targetEntity = AnswerRevision.class, cascade = CascadeType.REMOVE) @JoinColumn(name = "revisionOf") public List<AnswerRevision> getAnswerRevision() { return answerRevision; } private void setAnswerRevision(List<AnswerRevision> answerRevision) { this.answerRevision = answerRevision; } @Transient public static Answer load(Serializable id) throws FindByPrimaryKeyException { return (Answer) PersistenceHome.findByPrimaryKey(Answer.class, id); } @Transient public JSONObject jsonify(QAOperator logged, boolean getComments) { Answer answer = this; JSONObject t = new JSONObject(); t.element("propId", answer.getId()); t.element("propText", answer.getText()); t.element("propMan", answer.getQuestion().jsonify(logged, false)); t.element("propVotes", answer.getUpvotes().size()); t.element("propSelected", answer.isAccepted()); t.element("propOwnerName", answer.getOwner().getDisplayName()); t.element("propOwner", answer.getOwner().jsonify()); if (getComments){ JSONArray comments = new JSONArray(); for (Comment comment : getComments()) { JSONObject jc = comment.jsonify(logged); comments.add(jc); } t.element("propComments", comments); } if (logged != null) t.element("propIsOwner", answer.getOwner().getIntId() == logged.getIntId()); return t; } @Transient public boolean alreadyVoted(QAOperator logged) throws FindException { OqlQuery oq = new OqlQuery("from " + Upvote.class.getName() + " as up where up.operator=:op and up.answer=:answer" ); oq.getQuery().setEntity("op", logged).setEntity("answer", this); List<Upvote> votes = oq.list(); return votes.size()>0; } public static Comparator finalOrderComparator = new Comparator() { public int compare(Object o1, Object o2) { Answer p1 = (Answer) o1; Answer p2 = (Answer) o2; return p1.getFinalOrder() - p2.getFinalOrder(); } }; public String getContentRating() { return contentRating; } public void setContentRating(String contentRating) { this.contentRating = contentRating; } @Transient public void setAsAccepted() throws StoreException { for (Answer otherAnswer : getQuestion().getAnswersNotDeleted()) { if (!otherAnswer.getId().equals(getId()) && otherAnswer.isAccepted()) { otherAnswer.setAsRefuted(); } } setAccepted(true); setTotUpvotesAndAcceptance(getTotUpvotesAndAcceptance()+1000); getQuestion().setAnswerAcceptedOn(new Date()); getQuestion().setAcceptedAnswer(this); getQuestion().store(); store(); } @Transient public void setAsRefuted() throws StoreException { setAccepted(false); setTotUpvotesAndAcceptance(getTotUpvotesAndAcceptance()-1000); getQuestion().setAnswerAcceptedOn(null); getQuestion().setAcceptedAnswer(null); getQuestion().store(); store(); } @Transient public boolean likedBy(QAOperator QAOperator) { boolean likedBy = false; for (Upvote a : getUpvotes()) { if (a.getOperator() != null && a.getOperator().equals(QAOperator)) { likedBy = true; break; } } return likedBy; } @Transient public boolean hasPermissionFor(User u, QAPermission p) { boolean result = false; result = super.hasPermissionFor(u, p); if (!result) result = ((QAOperator)u).getKarma() > p.reputationRequired; return result; } @Transient public void hitAndNotify(QAOperator logged, QAEvent QAEvent) throws StoreException { hit(logged, QAEvent); // brick text, brick link, op name, op link getOwner().sendNote( I18n.get(QAEvent.toString() + "_SUBJECT"), // server, brick id, brick text, server, user id, user name I18n.get(QAEvent.toString() + "_BODY_%%_%%_%%_%%", ApplicationState.serverURL, getQuestion().getId() + "", JSP.htmlEncodeApexesAndTags(JSP.limWr(getText(), 30)), ApplicationState.serverURL, logged.getLoginName(), logged.getDisplayName()), QAEvent.toString()); } @Transient public void hit(QAOperator operator, QAEvent event) throws StoreException { Hit hit = Hit.newHit(this, operator, event.toString(), event.value); hit.setQuestionId(this.getIntId()); hit.store(); if (operator != null) { operator.setKarma(operator.getKarma() + event.value); operator.store(); } } public double getTotUpvotesAndAcceptance() { return totUpvotesAndAcceptance; } public void setTotUpvotesAndAcceptance(double totUpvotesAndAcceptance) { this.totUpvotesAndAcceptance = totUpvotesAndAcceptance; } }