libreccm-legacy/ccm-cms/src/com/arsdigita/cms/search/IntermediaQueryEngine.java

295 lines
13 KiB
Java
Executable File

/*
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.search;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import com.arsdigita.categorization.Category;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.ContentType;
// import com.arsdigita.cms.search.ContentTypeFilterSpecification;
// import com.arsdigita.cms.search.ContentTypeFilterType;
import com.arsdigita.kernel.PartyCollection;
import com.arsdigita.persistence.DataQuery;
import com.arsdigita.persistence.Filter;
import com.arsdigita.search.FilterSpecification;
import com.arsdigita.search.FilterType;
import com.arsdigita.search.Search;
import com.arsdigita.search.filters.CategoryFilterSpecification;
import com.arsdigita.search.filters.DateRangeFilterSpecification;
import com.arsdigita.search.filters.PartyFilterSpecification;
import com.arsdigita.search.intermedia.BaseQueryEngine;
public class IntermediaQueryEngine extends BaseQueryEngine {
public IntermediaQueryEngine() {
addColumn("version", "i.version");
addColumn("launch_date", "p.launch_date");
addColumn("last_modified", "audited.last_modified" );
addColumn("modifying_user", "audited.modifying_user" );
addColumn("creation_date", "audited.creation_date" );
addColumn("creation_user", "audited.creation_user");
// cg column map has been switched round (map fields to aliases)
// allowing us to override the score field to include keyword/title score
if (ContentSection.getConfig().scoreKeywordsAndTitle()) {
addColumn(SCORE, "((score(1) * " + Search.getConfig().getXMLContentWeight() + ") +"
+ " (score(2) * " + Search.getConfig().getRawContentWeight() + ") +"
+ " (score(3) * " + ContentSection.getConfig().getKeywordSearchWeight() + ") +"
+ " (score(4) * " + ContentSection.getConfig().getTitleSearchWeight() + "))");
}
// XXX: I am going to hell for the line below. I console myself only
// because this is a hack to work around a terrible interface.
// This line replaces the existing hash entry for 'search_content' and
// abuses the alias to add a left outer join.
// mbooth@redhat.com 02/02/2005
//
// amended to include (other) outer joins, otherwise you
// can't search for anything other than cms items
// cg - 11/10/2005
//
// likewise going to hell. Seb - 30/11/2005
addTable( "search_content", "c left outer join cms_pages p on ( p.item_id = c.object_id )"
+ " left outer join cms_items i on (c.object_id = i.item_id )"
+ " left outer join acs_auditing audited on (c.object_id = audited.object_id)" );
}
protected String cleanSearchString(String terms) {
if (ContentSection.getConfig().scoreKeywordsAndTitle()) {
return PathSearchSpecification.cleanSearchString(terms, " AND ");
} else {
return super.cleanSearchString(terms);
}
}
protected String getContainsClause (String terms) {
if (ContentSection.getConfig().scoreKeywordsAndTitle()) {
return PathSearchSpecification.containsClause("c", terms, "1", "2", "3", "4") + "\n";
} else {
return super.getContainsClause(terms);
}
}
protected void addFilter(DataQuery query,
FilterSpecification filter) {
super.addFilter(query, filter);
FilterType type = filter.getType();
if (ContentTypeFilterType.KEY.equals(type.getKey())) {
addContentTypeFilter(query, (ContentTypeFilterSpecification)filter);
} else if (VersionFilterType.KEY.equals(type.getKey())) {
addVersionFilter(query, (VersionFilterSpecification)filter);
} else if (LaunchDateFilterType.KEY.equals(type.getKey())) {
//addColumn("p.launch_date", "launch_date");
//addTable("cms_pages", "p");
//addCondition("c.object_id = p.item_id");
addLaunchDateFilter(query, (DateRangeFilterSpecification)filter);
} else if (LastModifiedDateFilterType.KEY.equals(type.getKey())) {
addLastModifiedDateFilter(query, (DateRangeFilterSpecification)filter);
} else if (CreationDateFilterType.KEY.equals(type.getKey())) {
addCreationDateFilter(query, (DateRangeFilterSpecification)filter);
} else if (LastModifiedUserFilterType.KEY.equals(type.getKey())) {
addPartyFilter(query, (PartyFilterSpecification)filter,
"modifying_user");
} else if (CreationUserFilterType.KEY.equals(type.getKey())) {
addPartyFilter(query, (PartyFilterSpecification)filter,
"creation_user");
} else if (CMSContentSectionFilterType.KEY.equals(type.getKey())) {
addCMSContentSectionFilter(query, (CMSContentSectionFilterSpecification)filter);
}
}
protected void addCMSContentSectionFilter(DataQuery query,
CMSContentSectionFilterSpecification filter) {
if (filter.getSections() == null) {
return;
}
Filter f = null;
if (filter.isExclusion()) {
f = query.addNotInSubqueryFilter(
"object_id",
"com.arsdigita.cms.getContentSectionItems");
} else {
f = query.addInSubqueryFilter(
"object_id",
"com.arsdigita.cms.getContentSectionItems");
}
f.set("sectionName", Arrays.asList(filter.getSections()));
}
protected void addVersionFilter(DataQuery query,
VersionFilterSpecification filter) {
Filter f = query.addFilter("nvl(version,'" + filter.getVersion() + "') = :version");
f.set("version", filter.getVersion());
}
protected void addLaunchDateFilter(DataQuery query,
DateRangeFilterSpecification filter) {
addDateRangeFilter(query, filter, "launch_date");
}
protected void addLastModifiedDateFilter(DataQuery query,
DateRangeFilterSpecification filter) {
// TODO: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=113394
// this will not work until the above bug is fixed
addDateRangeFilter(query, filter, "last_modified");
}
protected void addCreationDateFilter(DataQuery query,
DateRangeFilterSpecification filter) {
// TODO: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=113394
// this will not work until the above bug is fixed
addDateRangeFilter(query, filter, "creation_date");
}
private void addDateRangeFilter(DataQuery query,
DateRangeFilterSpecification filter,
String columnName) {
Date start = filter.getStartDate();
Date end = filter.getEndDate();
// XXX The query should actually be the commented out code at the
// bottom of this method instead of the query that we are using
// we have to comment it out because of a bug with persistence
DateFormat format = new SimpleDateFormat("MM/dd/yyyy");
if (start != null) {
Filter f = query.addFilter(columnName + " >= :" +
columnName + "StartDate");
// we truncate the value using java because we cannot do it
// using sql because of the persistence bug
Calendar startCal = GregorianCalendar.getInstance();
startCal.setTime(start);
/*
Calendar truncCal = GregorianCalendar.getInstance();
truncCal.set(Calendar.DAY_OF_YEAR, startCal.get(Calendar.DAY_OF_YEAR));
truncCal.set(Calendar.YEAR, startCal.get(Calendar.YEAR));
truncCal.set(Calendar.MINUTE, 0);
truncCal.set(Calendar.HOUR_OF_DAY, 0);
truncCal.set(Calendar.SECOND, 0);
f.set(columnName + "StartDate", truncCal.getTime());
*/
startCal.set(Calendar.MINUTE, 0);
startCal.set(Calendar.HOUR_OF_DAY, 0);
startCal.set(Calendar.SECOND, 0);
f.set(columnName + "StartDate", startCal.getTime());
}
if (end != null) {
Filter f = query.addFilter(columnName + " < :" +
columnName + "EndDate");
// we truncate the value using java because we cannot do it
// using sql because of the persistence bug
Calendar endCal = GregorianCalendar.getInstance();
endCal.setTime(end);
endCal.set(Calendar.MINUTE, 0);
endCal.set(Calendar.HOUR_OF_DAY, 0);
endCal.set(Calendar.SECOND, 0);
f.set(columnName + "EndDate", endCal.getTime());
}
/*
DateFormat format = new SimpleDateFormat("MM/dd/yyyy");
if (start != null) {
// XXX persistence bug - can't deal with functions on fields
Filter f = query.addFilter("trunc(" + columnName + ") >= to_date('" +
format.format(start) +
"','MM/DD/YYYY')");
}
if (end != null) {
// XXX persistence bug - can't deal with functions on fields
Filter f = query.addFilter("trunc(" + columnName + ") <= to_date('" +
format.format(end) +
"','MM/DD/YYYY')");
}
*/
}
protected void addPartyFilter(DataQuery query,
PartyFilterSpecification filter,
String columnName) {
PartyCollection parties = filter.getParties();
if (parties == null) {
return;
}
List partyIDs = new ArrayList();
while (parties.next()) {
partyIDs.add(parties.getID());
}
if (partyIDs.size() == 0) {
// no parties match so we make sure to return no results
query.addFilter("1=2");
} else {
Filter f = query.addFilter(columnName + " in :" +
columnName + "parties");
f.set(columnName + "parties", partyIDs);
}
}
protected void addContentTypeFilter(DataQuery query,
ContentTypeFilterSpecification filter) {
List l = new ArrayList();
ContentType[] types = filter.getTypes();
if (types == null || types.length == 0) {
return;
}
for (int i = 0 ; i < types.length ; i++) {
ContentType type = types[i];
l.add(type.getAssociatedObjectType());
}
Filter f = query.addFilter("object_type in :types");
f.set("types", l);
}
// Override to use query that takes account of bundles :-(
protected void addCategoryFilter(DataQuery query,
CategoryFilterSpecification filter) {
Category[] categories = filter.getCategories();
if (categories != null && categories.length > 0) {
List ids = new ArrayList();
for (int i = 0 ; i < categories.length ; i++) {
ids.add(categories[i].getID());
}
Filter f = query.addInSubqueryFilter(
"object_id",
"id",
"com.arsdigita.cms.searchCategoryObjects");
f.set("ids", ids);
f.set("pathLimit", new Integer(filter.isDescending() ? 999999 : 0));
}
}
}