/*
* Copyright (C) 2003-2008 eXo Platform SAS.
*
* 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.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.faq.service;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.exoplatform.commons.utils.ISO8601;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
/**
* Created by The eXo Platform SARL
*
* This object intermediate to give search Category or question in form advance search.
* All value user input search will save this object
*
* Author : Truong Nguyen
* truong.nguyen@exoplatform.com
* May 5, 2008, 3:48:51 PM
*/
public class FAQEventQuery {
public static final String FAQ_CATEGORY = "faqCategory";
public static final String FAQ_QUESTION = "faqQuestion";
public static final String CATEGORY_AND_QUESTION = "categoryAndQuestion";
private static Log log = ExoLogger.getLogger(FAQEventQuery.class);
private String type;
private String text;
private String name;
private String isModeQuestion;
private String moderator;
private String path;
private String author;
private String userId;
private String questionDisplayMode;
private String email;
private String question;
private String response;
private String comment;
private String attachment;
private List<String> userMembers;
private Calendar fromDate;
private Calendar toDate;
private String language;
private boolean isAnd = false;
private boolean isAdmin = false;
private List<String> viewingCategories;
private boolean isQuestionLevelSearch = false;
private boolean isLanguageLevelSearch = false;
private boolean isAnswerCommentLevelSearch = false;
private boolean isSearchOnDefaultLanguage = false;
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public void setQuestionDisplayMode(String questionDisplayMode) {
this.questionDisplayMode = questionDisplayMode;
}
public String getQuestionDisplayMode() {
return questionDisplayMode;
}
/**
* Instantiates a new fAQ event query.
*/
public FAQEventQuery() {
viewingCategories = new ArrayList<String>();
}
/**
* Gets the type.
*
* @return the type
*/
public String getType() {
return type;
}
/**
* Sets the type.
*
* @param type the new type
*/
public void setType(String type) {
this.type = type;
}
/**
* Gets the text.
*
* @return the text
*/
public String getText() {
return text;
}
/**
* Sets the text.
*
* @param text the new text
*/
public void setText(String text) {
this.text = text;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Sets the checks if is mode question.
*
* @param isModeQuestion the new checks if is mode question
*/
public void setIsModeQuestion(String isModeQuestion) {
this.isModeQuestion = isModeQuestion;
}
/**
* Gets the checks if is mode question.
*
* @return the checks if is mode question
*/
public String getIsModeQuestion() {
return isModeQuestion;
}
/**
* Sets the name.
*
* @param name the new name
*/
public void setName(String name) {
this.name = name;
}
/**
* Gets the moderator.
*
* @return the moderator
*/
public String getModerator() {
return moderator;
}
/**
* Sets the moderator.
*
* @param moderator the new moderator
*/
public void setModerator(String moderator) {
this.moderator = moderator;
}
/**
* Gets the path.
*
* @return the path
*/
public String getPath() {
return path;
}
/**
* Sets the path.
*
* @param path the new path
*/
public void setPath(String path) {
this.path = path;
}
/**
* Gets the author.
*
* @return the author
*/
public String getAuthor() {
return author;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserId() {
return userId;
}
/**
* Sets the author.
*
* @param author the new author
*/
public void setAuthor(String author) {
this.author = author;
}
/**
* Gets the email.
*
* @return the checks if is lock
*/
public String getEmail() {
return email;
}
/**
* Sets the email.
*
* @param email the new email
*/
public void setEmail(String email) {
this.email = email;
}
/**
* Gets the question.
*
* @return the question
*/
public String getQuestion() {
return question;
}
/**
* Sets the question.
*
* @param question the new question
*/
public void setQuestion(String question) {
this.question = question;
}
/**
* Gets the response.
*
* @return the response
*/
public String getResponse() {
return response;
}
/**
* Sets the response.
*
* @param response the new response
*/
public void setResponse(String response) {
this.response = response;
}
/**
* Gets the attachment.
*
* @return the attachment
*/
public String getAttachment() {
return attachment;
}
/**
* Sets the attachment.
*
* @param attachment the new attachment
*/
public void setAttachment(String attachment) {
this.attachment = attachment;
}
/**
* @return the userMembers
*/
public List<String> getUserMembers() {
return userMembers;
}
/**
* @param userMembers the userMembers to set
*/
public void setUserMembers(List<String> userMembers) {
this.userMembers = userMembers;
}
/**
* Gets the from date.
*
* @return the from date
*/
public Calendar getFromDate() {
return fromDate;
}
/**
* Sets the from date.
*
* @param fromDate the new from date
*/
public void setFromDate(Calendar fromDate) {
this.fromDate = fromDate;
}
/**
* Gets the to date.
*
* @return the to date
*/
public Calendar getToDate() {
return toDate;
}
/**
* Sets the to date.
*
* @param toDate the new to date
*/
public void setToDate(Calendar toDate) {
this.toDate = toDate;
}
/**
* Gets the checks.
*
* @return the checks if is true or false
*/
public boolean getIsAnd() {
return this.isAnd;
}
/**
* @return the isAdmin
*/
public boolean isAdmin() {
return isAdmin;
}
/**
* @param isAdmin the isAdmin to set
*/
public void setAdmin(boolean isAdmin) {
this.isAdmin = isAdmin;
}
/**
* This method is query on search
* Gets the path query.
*
* @return string the path query
*/
public String getQuery() throws Exception {
StringBuilder queryString = new StringBuilder();
// ######################### Category Search ###########################
if (type.equals(FAQ_CATEGORY)) { // Category Search
queryString = buildCategoryQuery();
// ###################### Question Search ############################
} else if (type.equals(FAQ_QUESTION)) {
queryString = buildQuestionQuery();
// ###################### Quick Search ###############################
} else if (type.equals(CATEGORY_AND_QUESTION)) {
queryString = buildCategoryAndQuestionQuery();
}
if (log.isDebugEnabled()) {
log.debug(queryString.toString());
}
return queryString.toString();
}
private StringBuilder buildCategoryQuery() {
StringBuilder queryString;
queryString = new StringBuilder();
queryString.append("/jcr:root").append(path);
queryString.append("//element(*,exo:faqCategory)");
queryString.append("[(@exo:isView='true') ");
if (text != null && text.length() > 0) {
queryString.append(" and (jcr:contains(., '").append(text).append("'))");
}
if (name != null && name.length() > 0) {
queryString.append(" and (jcr:contains(@exo:name, '").append(name).append("'))");
}
if (isModeQuestion != null && isModeQuestion.length() > 0 && !isModeQuestion.equals("AllCategories")) {
queryString.append(" and (@exo:isModerateQuestions='").append(isModeQuestion).append("')");
}
if (moderator != null && moderator.length() > 0) {
queryString.append(" and (jcr:contains(@exo:moderators, '").append(moderator).append("'))");
}
if (!isAdmin) {
queryString.append(" and (not(@exo:userPrivate) or @exo:userPrivate=''");
if (userMembers != null && !userMembers.isEmpty()) {
for (String str : userMembers) {
queryString.append(" or @exo:userPrivate='").append(str).append("' or @exo:moderators='").append(str).append("'");
}
}
queryString.append(")");
}
if (fromDate != null) {
queryString.append(" and (@exo:createdDate >= xs:dateTime('").append(ISO8601.format(fromDate)).append("'))");
}
if (toDate != null) {
queryString.append(" and (@exo:createdDate <= xs:dateTime('").append(ISO8601.format(toDate)).append("'))");
}
queryString.append("]");
return queryString;
}
private StringBuilder buildQuestionQuery() {
StringBuilder queryString;
// ## (questionSearch (or|and) languageSearch or answerSearch) and CategoryScoping and fulltextSearch ##
queryString = new StringBuilder();
isQuestionLevelSearch = false;
isAnswerCommentLevelSearch = false;
isAnd = false;
queryString.append("/jcr:root").append(path);
queryString.append("//* [");
// search on main questions
StringBuilder propertiesSearch = new StringBuilder("(");
isAnd = false;
if (author != null && author.length() > 0) {
if (isAnd)
propertiesSearch.append(" and ");
propertiesSearch.append("jcr:contains(@exo:author, '").append(author).append("')");
isAnd = true;
}
if (email != null && email.length() > 0) {
if (isAnd)
propertiesSearch.append(" and ");
propertiesSearch.append("jcr:contains(@exo:email, '").append(email).append("')");
isAnd = true;
}
if (fromDate != null) {
if (isAnd)
propertiesSearch.append(" and ");
// propertiesSearch.append("@exo:createdDate").append(" >= xs:dateTime('").append(ISO8601.format(fromDate)).append("')") ;
propertiesSearch.append("((@exo:createdDate >= xs:dateTime('").append(ISO8601.format(fromDate)).append("')) " + "or (@exo:dateResponse >= xs:dateTime('").append(ISO8601.format(fromDate)).append("')) " + "or (@exo:dateComment >= xs:dateTime('").append(ISO8601.format(fromDate)).append("')))");
isAnd = true;
}
if (toDate != null) {
if (isAnd)
propertiesSearch.append(" and ");
// propertiesSearch.append("@exo:createdDate").append(" <= xs:dateTime('").append(ISO8601.format(toDate)).append("')") ;
propertiesSearch.append("((@exo:createdDate <= xs:dateTime('").append(ISO8601.format(toDate)).append("')) " + "or (@exo:dateResponse <= xs:dateTime('").append(ISO8601.format(toDate)).append("')) " + "or (@exo:dateComment <= xs:dateTime('").append(ISO8601.format(toDate)).append("')))");
isAnd = true;
}
propertiesSearch.append(")");
if (propertiesSearch.length() > 2 || isSearchOnDefaultLanguage)
isQuestionLevelSearch = true;
// search on language questions
StringBuilder questionLanguageSearch = new StringBuilder("");
if (question != null && question.length() > 0) {
questionLanguageSearch.append("((exo:language='").append(language).append("')");
questionLanguageSearch.append(" and ( jcr:contains(@exo:title,'").append(question).append("') or jcr:contains(@exo:name, '").append(question).append("') )");
questionLanguageSearch.append(")");
if (isSearchOnDefaultLanguage)
isLanguageLevelSearch = false;
else
isLanguageLevelSearch = true;
}
// search on answers
StringBuilder answerSearch = new StringBuilder("");
if (response != null && response.length() > 0) {
answerSearch.append("( exo:responseLanguage='").append(language).append("'");
answerSearch.append(" and jcr:contains(@exo:responses,'" + response + "')");
answerSearch.append(")");
isAnswerCommentLevelSearch = true;
}
// search on comments
StringBuilder commentSearch = new StringBuilder();
if (comment != null && comment.length() > 0) {
commentSearch.append("( exo:commentLanguage='").append(language).append("'");
commentSearch.append(" and jcr:contains(@exo:comments,'" + comment + "')");
commentSearch.append(")");
isAnswerCommentLevelSearch = true;
}
// search on category scoping
StringBuilder searchCategoryScoping = new StringBuilder("(");
for (String category : getViewingCategories()) {
if (searchCategoryScoping.length() > 1)
searchCategoryScoping.append(" or ");
searchCategoryScoping.append("exo:categoryId='").append(category).append("'");
}
searchCategoryScoping.append(")");
if (isAnd) {
// System.out.println("questionSearch" + questionSearch.toString());
queryString.append(propertiesSearch.toString());
}
boolean isAdd = false;
// build scope of searching question, answer, comment
// queryString.append(" and "); // [properties search clause] and [ question, answer, comment search clause]
StringBuilder quesAnsComClause = new StringBuilder("");
if (questionLanguageSearch.length() > 0) {
quesAnsComClause.append("(").append(questionLanguageSearch.toString());
isAdd = true;
}
if (answerSearch.length() > 2) {
if (isAdd) {
quesAnsComClause.append(" or ").append(answerSearch.toString());
} else {
quesAnsComClause.append("(").append(answerSearch.toString());
isAdd = true;
}
}
if (commentSearch.length() > 2) {
if (isAdd) {
quesAnsComClause.append(" or ").append(commentSearch.toString());
} else {
quesAnsComClause.append("(").append(commentSearch.toString());
isAdd = true;
}
}
StringBuilder textSearch = new StringBuilder("");
if (text != null && text.length() > 0) {
textSearch.append("("); // open block.
textSearch.append("jcr:contains(., '").append(text).append("')");
textSearch.append(" and ( ").append(" exo:language='").append(language).append("'").append(" or exo:commentLanguage='").append(language).append("'").append(" or exo:responseLanguage='").append(language).append("'").append(")");
textSearch.append(")"); // close block.
isLanguageLevelSearch = false;
isAnswerCommentLevelSearch = false;
isQuestionLevelSearch = false;
}
if (textSearch.length() > 0) {
if (isAdd) {
quesAnsComClause.append(" or ").append(textSearch.toString());
} else {
quesAnsComClause.append("(").append(textSearch.toString());
isAdd = true;
}
}
if (isAdd)
quesAnsComClause.append(")"); // close question, answer, comment search clause.
if (quesAnsComClause.length() > 0) {
if (isAnd) {
queryString.append(" and ");
}
queryString.append(quesAnsComClause.toString());
}
if (!isAnd && !isAdd) { // if all of fields is empty of null, the search will be by language.
queryString.append("(").append(" exo:language='").append(language).append("'").append(" or exo:commentLanguage='").append(language).append("'").append(" or exo:responseLanguage='").append(language).append("'").append(")");
}
/*
* if(text != null && text.length() > 0 ) { if(isAdd){ queryString.append(" or ( jcr:contains(., '").append(text).append("')") ; }else { queryString.append("jcr:contains(., '").append(text).append("')") ; } queryString.append(" and ( " ) .append(" exo:language='").append(language).append("'") .append(" or exo:commentLanguage='").append(language).append("'")
* .append(" or exo:responseLanguage='").append(language).append("'") .append(")") ; if(isAdd) queryString.append(" ) " ) ; isAdd = true ; } else if(text == null && !isAnswerCommentLevelSearch && questionLanguageSearch.length() <= 0){ if(isAdd){ queryString.append(" and (exo:language='").append(language).append("')") ; }else { queryString.append("(exo:language='").append(language).append("')")
* ; isAdd = true ; } }
*/
if (!searchCategoryScoping.toString().equals("()")) {
if (isAnd || isAdd) {
queryString.append(" and ").append(searchCategoryScoping.toString());
} else {
queryString.append(searchCategoryScoping.toString());
isAdd = true;
}
}
queryString.append("]"); // close property constraint
return queryString;
}
private StringBuilder buildCategoryAndQuestionQuery() {
StringBuilder queryString;
// Quick search
queryString = new StringBuilder();
queryString.append("/jcr:root").append(path).append("//*[");
if (text != null && text.length() > 0) {
queryString.append(" jcr:contains(., '").append(text).append("')");
}
if (!isAdmin) {
queryString.append(" and ( ");
queryString.append("not(@exo:isApproved) or @exo:isApproved='true'");
if (userId != null && userId.length() > 0) {
queryString.append(" or exo:author='" + userId + "'");
}
queryString.append(" ) ");
}
// search on viewing categories
if (viewingCategories.size() > 0) {
queryString.append(" and (");
int i = 0;
for (String catId : viewingCategories) {
if (i > 0)
queryString.append(" or ");
// on questions
queryString.append("@exo:categoryId='").append(catId).append("'");
// on categories
queryString.append(" or @exo:id='").append(catId).append("'");
queryString.append(" and (");
queryString.append(" @exo:userPrivate=''");
// search restricted audience in category
if (userMembers != null && userMembers.size() > 0) {
for (String id : userMembers) {
queryString.append(" or @exo:userPrivate='").append(id).append("'");
}
}
queryString.append(" ) ");
i++;
}
queryString.append(")");
}
// search restricted audience
/*
* if(userMembers != null && userMembers.size() > 0) { queryString.append(" and (") ; int k = 0 ; for(String id : userMembers) { if(k > 0) queryString.append(" or "); queryString.append("(@exo:userPrivate='").append(id).append("')"); k ++ ; } queryString.append(" )") ; }else { queryString.append(" and not(@exo:userPrivate)") ; }
*/
// add condition for exo:dateResponse and exo:dateComment to search on answers & comments
if (fromDate != null) {
queryString.append(" and ((@exo:createdDate >= xs:dateTime('").append(ISO8601.format(fromDate)).append("')) " + "or (@exo:dateResponse >= xs:dateTime('").append(ISO8601.format(fromDate)).append("')) " + "or (@exo:dateComment >= xs:dateTime('").append(ISO8601.format(fromDate)).append("')))");
}
if (toDate != null) {
queryString.append(" and ((@exo:createdDate <= xs:dateTime('").append(ISO8601.format(toDate)).append("')) " + "or (@exo:dateResponse <= xs:dateTime('").append(ISO8601.format(toDate)).append("')) " + "or (@exo:dateComment <= xs:dateTime('").append(ISO8601.format(toDate)).append("')))");
}
queryString.append("]");
return queryString;
}
/**
* This method check date time user input interface
* Sets the date from to.
*
* @param fromDate the from date
* @param toDate the to date
* @param property the property
*
* @return the string
*/
public void setViewingCategories(List<String> viewingCategories) {
this.viewingCategories = viewingCategories;
}
public List<String> getViewingCategories() {
return viewingCategories;
}
public boolean isQuestionLevelSearch() throws Exception {
return isQuestionLevelSearch;
}
public boolean isAnswerCommentLevelSearch() throws Exception {
return isAnswerCommentLevelSearch;
}
public void setSearchOnDefaultLanguage(boolean isSearchOnDefaultLanguage) {
this.isSearchOnDefaultLanguage = isSearchOnDefaultLanguage;
}
public boolean isSearchOnDefaultLanguage() {
return isSearchOnDefaultLanguage;
}
public void setLanguageLevelSearch(boolean isLanguageLevelSearch) {
this.isLanguageLevelSearch = isLanguageLevelSearch;
}
public boolean isLanguageLevelSearch() {
return isLanguageLevelSearch;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getComment() {
return comment;
}
}