/*
* eXist Open Source Native XML Database
* Copyright (C) 2007 The eXist Project
* http://exist-db.org
*
* This program 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
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*
* @author Pierrick Brihaye <pierrick.brihaye@free.fr>
*/
package org.exist.indexing.spatial;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.log4j.Logger;
import org.exist.indexing.AbstractIndex;
import org.exist.indexing.IndexWorker;
import org.exist.indexing.StreamListener;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.btree.DBException;
import org.exist.util.DatabaseConfigurationException;
import org.w3c.dom.Element;
/**
*/
public abstract class AbstractGMLJDBCIndex extends AbstractIndex {
/**
* Holds the index ID. Notice that we delegate this task to the abstract JDBC class,
* not to the concrete HSQL (or whatever) one. This allows spatial functions to use
* the available JDBC index, whatever its underlying engine is.
*/
public final static String ID = AbstractGMLJDBCIndex.class.getName();
private final static Logger LOG = Logger.getLogger(AbstractGMLJDBCIndex.class);
/**
* An IndexWorker "pool"
*/
protected HashMap workers = new HashMap();
/**
* The connection to the DB that will be needed for global operations
*/
protected Connection conn = null;
/**
* The spatial operators to test spatial relationshipds beween geometries.
* See http://www.vividsolutions.com/jts/bin/JTS%20Technical%20Specs.pdf (chapter 11).
*/
public interface SpatialOperator {
public static int UNKNOWN = -1;
public static int EQUALS = 1;
public static int DISJOINT = 2;
public static int INTERSECTS = 3;
public static int TOUCHES = 4;
public static int CROSSES = 5;
public static int WITHIN = 6;
public static int CONTAINS = 7;
public static int OVERLAPS = 8;
}
protected int max_docs_in_context_to_refine_query = 10;
public AbstractGMLJDBCIndex() {
}
public void configure(BrokerPool pool, String dataDir, Element config) throws DatabaseConfigurationException {
super.configure(pool, dataDir, config);
try {
checkDatabase();
} catch (ClassNotFoundException e) {
throw new DatabaseConfigurationException(e.getMessage());
} catch (SQLException e) {
throw new DatabaseConfigurationException(e.getMessage());
}
}
public int getMaxDocsInContextToRefineQuery() {
return max_docs_in_context_to_refine_query;
}
public void open() throws DatabaseConfigurationException {
//Nothing particular to do : the connection will be opened on request
}
public void close() throws DBException {
Iterator i = workers.values().iterator();
while (i.hasNext()) {
AbstractGMLJDBCIndexWorker worker = (AbstractGMLJDBCIndexWorker)i.next();
//Flush any pending stuff
worker.flush();
//Reset state
worker.setDocument(null, StreamListener.UNKNOWN);
}
shutdownDatabase();
}
//Seems to never be used
public void sync() throws DBException {
//TODO : something useful here
/*
try {
if (conn != null)
conn.commit();
} catch (SQLException e) {
throw new DBException(e.getMessage());
}
*/
}
public void remove() throws DBException {
Iterator i = workers.values().iterator();
while (i.hasNext()) {
AbstractGMLJDBCIndexWorker worker = (AbstractGMLJDBCIndexWorker)i.next();
//Flush any pending stuff
worker.flush();
//Reset state
worker.setDocument(null, StreamListener.UNKNOWN);
}
removeIndexContent();
shutdownDatabase();
deleteDatabase();
}
public boolean checkIndex(DBBroker broker) {
return getWorker(broker).checkIndex(broker);
}
public abstract IndexWorker getWorker(DBBroker broker);
/**
* Checks if the JDBC database that contains the indexed spatial data is available an reachable.
* Creates it if necessary.
*
* @throws ClassNotFoundException if the JDBC driver can not be found
* @throws SQLException if the database is not reachable
*/
protected abstract void checkDatabase() throws ClassNotFoundException, SQLException;
/**
* Shuts down the JDBC database that contains the indexed spatial data.
*
* @throws DBException
*/
protected abstract void shutdownDatabase() throws DBException;
/**
* Deletes the JDBC database that contains the indexed spatial data.
*
* @throws DBException
*/
protected abstract void deleteDatabase() throws DBException;
/**
* Deletes the spatial data contained in the JDBC database.
*
* @throws DBException
*/
protected abstract void removeIndexContent() throws DBException;
/**
* Convenience method that can be used by the IndexWorker to acquire a connection
* to the JDBC database that contains the indexed spatial data.
*
* @param broker the broker that will use th connection
* @return the connection
*/
protected abstract Connection acquireConnection(DBBroker broker) throws SQLException;
/**
* Convenience method that can be used by the IndexWorker to release a connection
* to the JDBC database that contains the indexed spatial data. This connection should have been
* previously acquired by {@link org.exist.indexing.spatial.AbstractGMLJDBCIndex#acquireConnection(DBBroker)}
*
* @param broker the broker that will use th connection
*
*/
protected abstract void releaseConnection(DBBroker broker) throws SQLException;
}