/* * 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.services.wcm.utils; import java.util.Calendar; import org.apache.commons.lang.StringUtils; import org.exoplatform.commons.utils.ISO8601; /** * Created by The eXo Platform SAS * Author : Hoa Pham * hoa.pham@exoplatform.com * Oct 7, 2008 */ /* * This class is implementation of AbstractQueryBuilder for sql-based query. * This class help developer create sql query statement easier. * */ public class SQLQueryBuilder extends AbstractQueryBuilder { /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#isNull(java.lang * .String, org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void isNull(String propertyName, LOGICAL condition) { if(condition == LOGICAL.AND) propertiesClause.append(" AND").append(propertyName).append("IS NULL "); else if(condition == LOGICAL.OR) propertiesClause.append(" OR").append(propertyName).append("IS NULL "); else propertiesClause.append(propertyName).append("IS NULL "); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#isNotNull(java * .lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void isNotNull(String propertyName, LOGICAL condition) { if(condition == LOGICAL.AND) propertiesClause.append("AND ").append(propertyName).append(" IS NOT NULL "); else if(condition == LOGICAL.OR) propertiesClause.append("OR ").append(propertyName).append(" IS NOT NULL "); else propertiesClause.append(propertyName).append(" IS NOT NULL "); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#lessThan(java. * lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void lessThan(String propertyName, String value, LOGICAL condition) { comparison(propertyName,value,condition,"<"); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#greaterThan(java * .lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void greaterThan(String propName, String value, LOGICAL condition) { comparison(propName,value,condition,">"); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#lessThanOrEqual * (java.lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void lessThanOrEqual(String propName, String value, LOGICAL condition) { comparison(propName,value,condition,"<="); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#greaterOrEqual * (java.lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void greaterOrEqual(String propName,String value, LOGICAL condition) { comparison(propName,value,condition,">="); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#equal(java.lang * .String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void equal(String propName, String value , LOGICAL condition) { comparison(propName,value,condition,"="); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#notEqual(java. * lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void notEqual(String propName, String value, LOGICAL condition) { if(condition == LOGICAL.AND) propertiesClause.append("AND ").append(propName).append(" <> '").append(value).append("' "); else if(condition == LOGICAL.OR) propertiesClause.append("OR ").append(propName).append(" <> '").append(value).append("' "); else propertiesClause.append(propName).append(" <> '").append(value).append("' "); } /** * Comparison. * * @param propName the prop name * @param value the value * @param condition the condition * @param symbol the symbol */ private void comparison(String propName, String value, LOGICAL condition, String symbol) { if(condition == LOGICAL.AND) propertiesClause.append("AND ").append(propName).append(" ").append(symbol).append(" '").append(value).append("' "); else if(condition == LOGICAL.OR) propertiesClause.append("OR ").append(propName).append(" ").append(symbol).append(" '").append(value).append("' "); else propertiesClause.append(propName).append(" ").append(symbol).append(" '").append(value).append("' "); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#like(java.lang * .String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void like(String propName, String value, LOGICAL condition) { if(condition == LOGICAL.AND) propertiesClause.append("AND ").append(propName).append(" LIKE '").append(value).append("%' "); else if(condition == LOGICAL.OR) propertiesClause.append("OR ").append(propName).append(" LIKE '").append(value).append("%' "); else propertiesClause.append(propName).append(" LIKE '").append(value).append("%' "); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#reference(java * .lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void reference(String propName, String value, LOGICAL condition) { } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#beforeDate(java * .lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void beforeDate(String propName, String comparedDate, LOGICAL condition) { Calendar calendar = ISO8601.parse(comparedDate); String time = calendar.getTime().toString(); if(condition == LOGICAL.AND) propertiesClause.append("AND ").append(propName).append(" <= '").append(time).append("' "); else if(condition == LOGICAL.OR) propertiesClause.append("OR ").append(propName).append(" <= '").append(time).append("' "); else propertiesClause.append(propName).append(" <= '").append(time).append("' "); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#afterDate(java * .lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void afterDate(String propName, String comparedDate, LOGICAL condition) { Calendar calendar = ISO8601.parse(comparedDate); String time = calendar.getTime().toString(); if(condition == LOGICAL.AND) propertiesClause.append("AND ").append(propName).append(" >= '").append(time).append("' "); else if(condition == LOGICAL.OR) propertiesClause.append("OR ").append(propName).append(" >= '").append(time).append("' "); else propertiesClause.append(propName).append(" >= '").append(time).append("' "); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#betweenDates(java * .lang.String, java.lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void betweenDates(String propName, String startDate, String endDate, LOGICAL condition) { String startTime = ISO8601.parse(startDate).getTime().toString(); String endTime = ISO8601.parse(endDate).getTime().toString(); if (condition == LOGICAL.AND) propertiesClause.append("AND ") .append(propName) .append(" between TIMESTAMP '") .append(startTime) .append("' and TIMESTAMP '") .append(endTime) .append("' "); else if (condition == LOGICAL.OR) propertiesClause.append("OR ") .append(propName) .append(" between TIMESTAMP '") .append(startTime) .append("' and TIMESTAMP '") .append(endTime) .append("' "); else propertiesClause.append(propName) .append(" between TIMESTAMP '") .append(startTime) .append("' and TIMESTAMP '") .append(endTime) .append("' "); } public void betweenDates(String propName, Calendar startDate, Calendar endDate, LOGICAL condition) { String startTime = ISO8601.format(startDate); String endTime = ISO8601.format(endDate); if (condition == LOGICAL.AND) propertiesClause.append("AND ") .append(propName) .append(" between TIMESTAMP '") .append(startTime) .append("' and TIMESTAMP '") .append(endTime) .append("' "); else if (condition == LOGICAL.OR) propertiesClause.append("OR ") .append(propName) .append(" between TIMESTAMP '") .append(startTime) .append("' and TIMESTAMP '") .append(endTime) .append("' "); else propertiesClause.append(propName) .append(" between TIMESTAMP '") .append(startTime) .append("' and TIMESTAMP '") .append(endTime) .append("' "); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#setQueryPath(java * .lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.PATH_TYPE) */ public void setQueryPath(String path, PATH_TYPE pathtype) { if(StringUtils.isEmpty(path)) return; if (PATH_TYPE.EXACT == pathtype) { if (path.indexOf("[%]") > 0) pathClause = new StringBuilder().append("jcr:path LIKE '").append(path).append("' "); else pathClause = new StringBuilder().append("jcr:path = '").append(path).append("' "); } else if (PATH_TYPE.CHILDNODES == pathtype) { pathClause = new StringBuilder().append("jcr:path LIKE '") .append(path) .append("/%'") .append("AND NOT jcr:path like '") .append(path) .append("/%/%' "); } else if (PATH_TYPE.DECENDANTS == pathtype) { pathClause = new StringBuilder().append("jcr:path LIKE '").append(path).append("/%' "); } else if (PATH_TYPE.DECENDANTS_OR_SELFT == pathtype) { pathClause = new StringBuilder().append("jcr:path LIKE '") .append(path) .append("'") .append("OR jcr:path LIKE '") .append(path) .append("/%' "); } } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#contains(java. * lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void contains(String scope, String term, LOGICAL condition) { if (scope == null) scope = "."; if (LOGICAL.AND == condition) containsClause.append("AND CONTAINS(").append(scope).append(",'").append(term).append("') "); else if (LOGICAL.OR == condition) containsClause.append("OR CONTAINS(").append(scope).append(",'").append(term).append("') "); else containsClause.append("CONTAINS(").append(scope).append(",'").append(term).append("') "); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#notContains(java * .lang.String, java.lang.String, * org.exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void notContains(String scope, String term, LOGICAL condition) { if (scope == null) scope = "."; if (LOGICAL.AND == condition) containsClause.append("AND NOT CONTAINS(") .append(scope) .append(",'") .append(term) .append("') "); else if (LOGICAL.OR == condition) containsClause.append("OR NOT CONTAINS(") .append(scope) .append(",'") .append(term) .append("') "); else containsClause.append("NOT CONTAINS(").append(scope).append(",'").append(term).append("') "); } /* (non-Javadoc) * @see org.exoplatform.services.wcm.search.AbstractQueryBuilder#fromNodeTypes(java.lang.String[]) */ public void fromNodeTypes(String[] nodetypes) { if(nodetypes == null) { fromClause = new StringBuilder("FROM nt:base"); return; } fromClause = new StringBuilder("FROM "); for(int i = 0; i<nodetypes.length; i++) { fromClause.append(nodetypes[i]); if(i<nodetypes.length-1) fromClause.append(","); } } /* (non-Javadoc) * @see org.exoplatform.services.wcm.search.AbstractQueryBuilder#selectTypes(java.lang.String[]) */ public void selectTypes(String[] returnTypes) { if(returnTypes == null) { selectClause = new StringBuilder("SELECT * "); return; } selectClause = new StringBuilder("SELECT "); for(int i = 0; i<returnTypes.length; i++) { selectClause.append(returnTypes[i]); if(i<returnTypes.length-1) selectClause.append(","); selectClause.append(" "); } } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#orderBy(java.lang * .String, org.exoplatform.services.wcm.search.AbstractQueryBuilder.ORDERBY) */ public void orderBy(String properyName, ORDERBY orderby) { if(orderByClause.length()>0) orderByClause = orderByClause.append(", "); if(ORDERBY.ASC == orderby) orderByClause.append(properyName).append(" ASC"); else orderByClause.append(properyName).append(" DESC"); } /* (non-Javadoc) * @see org.exoplatform.services.wcm.search.AbstractQueryBuilder#excerpt(boolean) */ public void excerpt(boolean enable) { if(enable) excerptClause = new StringBuilder("excerpt(.)"); } /* (non-Javadoc) * @see org.exoplatform.services.wcm.search.AbstractQueryBuilder#spellCheck(java.lang.String) */ public void spellCheck(String value) { } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#openGroup(org. * exoplatform.services.wcm.search.AbstractQueryBuilder.LOGICAL) */ public void openGroup(LOGICAL logical) { if(LOGICAL.AND == logical) propertiesClause = propertiesClause.append("AND( "); else if(LOGICAL.OR == logical) propertiesClause = propertiesClause.append("OR( "); else if(LOGICAL.AND_NOT == logical) propertiesClause = propertiesClause.append("AND NOT("); else if(LOGICAL.OR_NOT == logical) propertiesClause = propertiesClause.append("OR NOT("); else propertiesClause = propertiesClause.append("( "); } /* (non-Javadoc) * @see org.exoplatform.services.wcm.search.AbstractQueryBuilder#closeGroup() */ public void closeGroup() { propertiesClause = propertiesClause.append(")"); } /* (non-Javadoc) * @see org.exoplatform.services.wcm.search.AbstractQueryBuilder#createQueryStatement() */ public String createQueryStatement() { StringBuffer statement = new StringBuffer(); statement = statement.append(selectClause.toString()) .append(fromClause.toString()) .append(" WHERE "); if (containsClause.length() > 0) { statement = statement.append(containsClause.toString()); if (pathClause.length() > 0) { statement = statement.append("AND ").append(pathClause.toString()); } } else { if (pathClause.length() > 0) { statement = statement.append(pathClause.toString()); } } if (propertiesClause.length() > 0) { String propertiesStr = propertiesClause.toString(); if((propertiesStr.startsWith("AND") || propertiesStr.startsWith(" AND")) && statement.toString().endsWith("WHERE ")) propertiesStr = propertiesStr.substring(propertiesStr.lastIndexOf("AND") + 1, propertiesStr.length()); statement = statement.append(propertiesStr); } if (orderByClause.length() > 0) { statement = statement.append("ORDER BY ").append(orderByClause.toString()); } return statement.toString(); } /* * (non-Javadoc) * @see * org.exoplatform.services.wcm.search.AbstractQueryBuilder#merge(org.exoplatform * .services.wcm.search.AbstractQueryBuilder) */ public void merge(AbstractQueryBuilder other) { } public void queryByNodeName(String rootPath, String nodeName) { pathClause = new StringBuilder().append(" jcr:path LIKE '") .append(rootPath) .append("/%/") .append(nodeName) .append("' ") .append(" or jcr:path like '") .append(rootPath) .append("/") .append(nodeName) .append("' "); } }