UnifiedQuery.java
/*
* Copyright (C) 2003-2013 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 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 <http://www.gnu.org/licenses/>.
*/
package org.exoplatform.calendar.service.impl;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.jcr.query.Query;
import org.exoplatform.calendar.service.CalendarEvent;
import org.exoplatform.calendar.service.EventQuery;
import org.exoplatform.calendar.service.Utils;
import org.exoplatform.commons.utils.ISO8601;
/**
* Created by The eXo Platform SAS
* Author : eXoPlatform
* exo@exoplatform.com
* Jan 23, 2013
*/
public class UnifiedQuery extends EventQuery {
private Set<String> excludePrivateEventInCalendars = Collections.EMPTY_SET;
public Set<String> getExcludePrivateEventInCalendars() {
return Collections.unmodifiableSet(excludePrivateEventInCalendars);
}
public void setExcludePrivateEventInCalendars(Set<String> excludePrivateEventInCalendars) {
this.excludePrivateEventInCalendars = excludePrivateEventInCalendars;
}
public String getQueryStatement() throws Exception {
StringBuffer queryString = new StringBuffer("");
if (getQueryType().equals(Query.SQL)) {
String text = getText() ;
if (!Utils.isEmpty(text)) {
queryString = new StringBuffer("SELECT ");
queryString.append(repeat("%s", Arrays.asList(Utils.SELECT_FIELDS), ","));
queryString.append(" FROM " + getNodeType() + " WHERE ");
if(!Utils.isEmpty(getCalendarPath())) {
queryString.append("jcr:path LIKE '").append(getCalendarPath()).append("/%/%' AND ");
}
if (getCalendarId() != null && getCalendarId().length > 0) {
queryString.append("(");
String[] calendarIds = getCalendarId();
for (int i = 0; i < calendarIds.length; i++) {
if (i != 0) {
queryString.append(" OR ");
}
String calendarId = calendarIds[i];
queryString.append("(").append(Utils.EXO_CALENDAR_ID).append(" = '").append(calendarId).append("'");
if(excludePrivateEventInCalendars != null && excludePrivateEventInCalendars.contains(calendarId)) {
queryString.append(" AND ").append(Utils.EXO_IS_PRIVATE).append(" = 'false' ");
}
queryString.append(")");
}
queryString.append(") AND ");
}
if (!Utils.isEmpty(getEventType())) {
queryString.append(Utils.EXO_EVENT_TYPE).append(" = '").append(getEventType()).append("' AND (");
}
Collection<String> inputs = parse(text) ;
int inputCount = 0 ;
for(String keyword : inputs) {
if(inputCount > 0) queryString.append(" AND ");
queryString.append("CONTAINS(*,'").append(escapeContainsQuery(keyword)).append("')");
inputCount ++ ;
}
if (!Utils.isEmpty(getEventType())) {
queryString.append(") ");
}
if (getFromDate() != null && CalendarEvent.TYPE_EVENT.equals(getEventType())) {
queryString.append(" AND ").append(queryStringForFromTime(getFromDate()));
}
if (!Utils.isEmpty(getState())) {
if(getState().indexOf(Utils.COLON) >0)
for(String state : getState().split(Utils.COLON))
queryString.append(" AND ").append(Utils.EXO_EVENT_STATE).append(" <> '").append(state).append("'");
}
if(getOrderBy() != null && getOrderBy().length > 0) {
queryString.append(" ORDER BY ").append(getOrderBy()[0]);
if(!Utils.isEmpty(getOrderType())) queryString.append(Utils.SPACE).append(getOrderType().toUpperCase());
}
}
}
return queryString.toString();
}
public static List<String> parse(String input) {
List<String> terms = new LinkedList<String>();
Matcher matcher = Pattern.compile("\"([^\"]+)\"").matcher(input);
while (matcher.find()) {
String founds = matcher.group(1);
terms.add(founds);
}
String remain = matcher.replaceAll("").replaceAll("\"\"", "").trim(); //remove all remaining double quotes
if(!remain.isEmpty()) terms.addAll(Arrays.asList(remain.split("\\s+")));
return terms;
}
private static String repeat(String format, Collection<String> strArr, String delimiter){
StringBuilder sb=new StringBuilder();
String delim = "";
for(String str:strArr) {
sb.append(delim).append(String.format(format, str));
delim = delimiter;
}
return sb.toString();
}
/*
* builds query string to check if event is not end after a specified date
*/
private String queryStringForFromTime(java.util.Calendar cal) {
StringBuilder sb = new StringBuilder("(");
sb.append(Utils.EXO_TO_DATE_TIME).append(" >= TIMESTAMP '").append(ISO8601.format(cal)).append("'"); // to date is after cal
sb.append(" OR ").append("(");
sb.append(Utils.EXO_REPEAT).append(" <> '").append(CalendarEvent.RP_NOREPEAT).append("'"); // if event is repeated
sb.append(" AND ").append("(");
sb.append(Utils.EXO_REPEAT_FINISH_DATE).append(" >= TIMESTAMP '").append(ISO8601.format(cal)).append("'"); // having the repeat finish date after cal
sb.append(" OR ");
sb.append(Utils.EXO_REPEAT_FINISH_DATE).append(" IS ").append("NULL"); // having no property exo:repeatFinishDate (never end event)
sb.append(")))");
return sb.toString();
}
}