/* * #! * 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.topicmaps.query.spi; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; import net.ontopia.topicmaps.core.TopicMapStoreIF; import net.ontopia.topicmaps.impl.rdbms.RDBMSTopicMapStore; import net.ontopia.utils.OntopiaRuntimeException; import net.ontopia.utils.PropertyUtils; import net.ontopia.utils.StringUtils; /** * EXPERIMENTAL: RDBMS searcher implementation that executes a SQL * query in the same database as the topic map is stored in. The query * must return two columns, the first the object id of the result * topic map object (a string), the second the score (a float).<p> * * The name of the predicate is used as the key to look up the query * itself. The queries are read from a properties file called * RDBMSSearcher.props from the CLASSPATH.<p> * * The sql query can be specified directly via the 'sql' URI parameter * on the searcher class. Just make sure that the query is URI * encoded. The query file name can be overriden with the 'queryFile' * parameter. */ public class RDBMSSearcher extends AbstractSearcher { /** * PUBLIC: The mandatory default constructor. */ public RDBMSSearcher() { } public int getValueType() { return SearcherIF.OBJECT_ID; } public SearchResultIF getResult(String query) { return new SearchResult(query); } private class SearchResult extends AbstractSearchResult { PreparedStatement pstm; ResultSet rs; SearchResult(String query) { TopicMapStoreIF store = topicmap.getStore(); if (store instanceof RDBMSTopicMapStore) { try { Connection conn = ((RDBMSTopicMapStore)store).getConnection(); pstm = conn.prepareStatement(getSQL()); pstm.setString(1, query); rs = pstm.executeQuery(); } catch (SQLException e) { throw new OntopiaRuntimeException(e); } } } private String getSQL() { String sql = (String)parameters.get("sql"); if (sql == null) { String queryName = (String)parameters.get("queryName"); if (queryName == null) queryName = predicateName; String queryFile = (String)parameters.get("queryFile"); if (queryFile == null) queryFile = "RDBMSSearcher.props"; try { Properties props = PropertyUtils.loadPropertiesFromClassPath(queryFile); sql = props.getProperty(queryName); } catch (IOException e) { throw new OntopiaRuntimeException(e); } if (sql == null) throw new OntopiaRuntimeException("Query with name '" + queryName + "' not found in " + queryFile + "."); } sql = StringUtils.replace(sql, "${topicmap}", topicmap.getObjectId().substring(1)); sql = StringUtils.replace(sql, "${term}", "?"); return sql; } public boolean next() { if (rs == null) return false; try { return rs.next(); } catch (SQLException e) { throw new OntopiaRuntimeException(e); } } public Object getValue() { try { return rs.getString(1); } catch (SQLException e) { throw new OntopiaRuntimeException(e); } } public float getScore() { try { return rs.getFloat(2); } catch (SQLException e) { throw new OntopiaRuntimeException(e); } } public void close() { try { if (rs != null) rs.close(); if (pstm != null) pstm.close(); } catch (SQLException e) { throw new OntopiaRuntimeException(e); } } }; }