/*
* #!
* Ontopia Engine
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* !#
*/
package net.ontopia.infoset.fulltext.impl.rdbms;
import java.io.IOException;
import net.ontopia.infoset.fulltext.core.SearchResultIF;
import net.ontopia.infoset.fulltext.core.SearcherIF;
import net.ontopia.persistence.proxy.QueryResultIF;
import net.ontopia.persistence.proxy.TransactionIF;
import net.ontopia.topicmaps.core.TopicMapIF;
import net.ontopia.topicmaps.core.index.IndexIF;
import net.ontopia.topicmaps.impl.rdbms.RDBMSTopicMapStore;
import net.ontopia.topicmaps.impl.rdbms.RDBMSTopicMapTransaction;
import net.ontopia.topicmaps.impl.utils.AbstractIndex;
import net.ontopia.topicmaps.impl.utils.TopicMapTransactionIF;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* INTERNAL: A generic RDBMS fulltext searcher implementation. Note that the class
* only accepts an RDBMS topic map in its constructor.
* <p>
*/
public class RDBMSSearcher extends AbstractIndex implements SearcherIF {
// Define a logging category.
static Logger log = LoggerFactory.getLogger(RDBMSSearcher.class.getName());
protected final static int FT_PLATFORM_GENERIC = 1;
protected final static int FT_PLATFORM_ORACLE_TEXT = 2;
protected final static int FT_PLATFORM_TSEARCH2 = 4;
protected final static int FT_PLATFORM_SQLSERVER = 8;
protected RDBMSTopicMapTransaction tmtxn;
protected int ft_platform = FT_PLATFORM_GENERIC;
protected static String[] fnames = new String[] { "class", "object_id",
"content", "score" // TODO: Add "address" and "notation" later
};
public RDBMSSearcher(TopicMapIF topicmap) {
this(((RDBMSTopicMapStore)topicmap.getStore()).getTransaction());
}
public RDBMSSearcher(TopicMapTransactionIF txn) {
this.tmtxn = (RDBMSTopicMapTransaction)txn;
// figure out what the fulltext platform is
String platform = ((net.ontopia.persistence.proxy.RDBMSStorage) this.tmtxn
.getTransaction().getStorageAccess().getStorage())
.getProperty("net.ontopia.infoset.fulltext.impl.rdbms.RDBMSSearcher.type");
if (platform != null) {
if (platform.equals("oracle_text"))
this.ft_platform = FT_PLATFORM_ORACLE_TEXT;
else if (platform.equals("tsearch2"))
this.ft_platform = FT_PLATFORM_TSEARCH2;
else if (platform.equals("postgresql"))
this.ft_platform = FT_PLATFORM_TSEARCH2;
else if (platform.equals("sqlserver"))
this.ft_platform = FT_PLATFORM_SQLSERVER;
else if (platform.equals("generic"))
this.ft_platform = FT_PLATFORM_GENERIC;
}
// DEPRECATED: check platforms property as fallback
if (this.ft_platform == FT_PLATFORM_GENERIC) {
String[] platforms = ((net.ontopia.persistence.proxy.RDBMSStorage) this.tmtxn
.getTransaction().getStorageAccess().getStorage()).getPlatforms();
for (int i = 0; i < platforms.length; i++) {
if ("oracle_text".equals(platforms[i])) {
this.ft_platform = FT_PLATFORM_ORACLE_TEXT;
break;
}
}
}
}
public SearchResultIF search(String query) throws IOException {
TransactionIF txn = tmtxn.getTransaction();
Object[] params = getParameters(escapeQuery(query), tmtxn.getTopicMap());
String queryName;
if (ft_platform == FT_PLATFORM_ORACLE_TEXT)
queryName = "RDBMSSearcher.searchLike:oracle_text";
else if (ft_platform == FT_PLATFORM_TSEARCH2)
queryName = "RDBMSSearcher.searchLike:tsearch2";
else if (ft_platform == FT_PLATFORM_SQLSERVER)
queryName = "RDBMSSearcher.searchLike:sqlserver";
else
queryName = "RDBMSSearcher.searchLike:generic";
QueryResultIF result = (QueryResultIF) txn.executeQuery(queryName, params);
return new RDBMSSearchResult(result, fnames);
}
protected String escapeQuery(String query) {
if (ft_platform == FT_PLATFORM_GENERIC) {
return '%' + query + '%';
//!} else if (ft_platform == FT_PLATFORM_ORACLE_TEXT) { // no escaping for now
//! return '{' + StringUtils.replace(query, "}", "\\}") + '}';
} else {
return query;
}
}
/**
* INTERNAL: Override this method if the parameters to be used by the query is
* different from the default. If the parameter types are different or the
* order is different this method must be overridden.
*/
protected Object[] getParameters(String query, TopicMapIF topicmap) {
if (ft_platform == FT_PLATFORM_TSEARCH2) {
query = query.replaceAll("\\s", " & ");
return new Object[] { query, topicmap, query, query, topicmap, query, query, topicmap, query };
} else if (ft_platform == FT_PLATFORM_SQLSERVER)
return new Object[] { query, topicmap, query, topicmap, query, topicmap };
else
return new Object[] { topicmap, query, topicmap, query, topicmap, query };
}
public void close() throws IOException {
tmtxn = null;
}
// --- IndexIF implementation
public IndexIF getIndex() {
return this;
}
public boolean isAutoUpdated() {
return true;
}
public void refresh() {
// TODO: Issue query in database? One example is Oracle Text,
// where you explicitly have to call alter index in order to
// rebuild indexes.
}
// TODO: Add command-line support?
}