Added:
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/BasicRelationalRecordResolver.java
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/BasicSQLTranslator.java
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/CqlQueryTranslator.java
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RecordResolver.java
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RelationalQueryResult.java
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RelationalRecordIterator.java
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/SRWRelationalDatabase.java
Log:
Added relational database translator classes.
Added:
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/BasicRelationalRecordResolver.java
==============================================================================
--- (empty file)
+++
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/BasicRelationalRecordResolver.java
Sun Jul 12 07:58:40 2009
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2006 OCLC Online Computer Library Center, Inc.
+ *
+ * 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.
+ */
+/**
+ * BasicLuceneRecordResolver.java
+ *
+ * Created on November 1, 2006, 1:40 PM
+ */
+
+package org.nescent.phylr.relational;
+
+import gov.loc.www.zing.srw.ExtraDataType;
+
+import java.sql.ResultSet;
+import java.util.Iterator;
+import java.util.Properties;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.oclc.os.SRW.Record;
+import org.oclc.os.SRW.Utilities;
+
+
+/**
+ *
+ * @author levan
+ */
+public class BasicRelationalRecordResolver implements RecordResolver {
+ static Log log=LogFactory.getLog(BasicRelationalRecordResolver.class);
+ static final String
LUCENE_SCHEMA_ID="info:srw/schema/1/LuceneDocument";
+
+ /** Creates a new instance of BasicLuceneRecordResolver */
+ public BasicRelationalRecordResolver() {
+ }
+
+// Not legal until JDK 6 @Override
+ public void init(Properties properties) {
+ }
+
+// Not legal until JDK 6 @Override
+ public Record resolve(ResultSet result, String IdFieldName,
ExtraDataType extraDataType) {
+ /*
+ // Enumeration fields=doc.fields(); // lucene 1.4
+ Iterator fields=doc.getFields().iterator();
+ Field field;
+ StringBuffer sb=new StringBuffer("<LuceneDocument
xmlns=\"http://www.oclc.org/LuceneDocument\">");
+ // while(fields.hasMoreElements()) {
+ while(fields.hasNext()) {
+ // field=(Field)fields.nextElement();
+ field=(Field)fields.next();
+ sb.append("<field name=\"").append(field.name()).append("\">");
+
+ String fieldVal = field.stringValue();
+ int firstNewline = fieldVal.indexOf("\n");
+ log.error("Trimmed: " + fieldVal.substring(0,firstNewline));
+
+ // sb.append(fieldVal.substring(firstNewline));
+ sb.append("</field>");
+ }
+ sb.append("</LuceneDocument>");
+ return new Record(sb.toString(), LUCENE_SCHEMA_ID);
+ */
+ return null;
+ }
+}
Added:
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/BasicSQLTranslator.java
==============================================================================
--- (empty file)
+++
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/BasicSQLTranslator.java
Sun Jul 12 07:58:40 2009
@@ -0,0 +1,24 @@
+package org.nescent.phylr.relational;
+
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.oclc.os.SRW.SRWDiagnostic;
+import org.oclc.os.SRW.SortTool;
+import org.z3950.zing.cql.CQLNode;
+
+public class BasicSQLTranslator implements CqlQueryTranslator {
+ private static Log log= LogFactory.getLog(BasicSQLTranslator.class);
+
+// Not legal until JDK 6 @Override
+ public void init(Properties properties, SRWRelationalDatabase ldb)
throws InstantiationException {
+ }
+
+// Not legal until JDK 6 @Override
+ public String makeQuery(CQLNode node, SortTool sortTool) throws
SRWDiagnostic {
+ return "";
+ }
+
+
+}
Added:
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/CqlQueryTranslator.java
==============================================================================
--- (empty file)
+++
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/CqlQueryTranslator.java
Sun Jul 12 07:58:40 2009
@@ -0,0 +1,26 @@
+/*
+ * CqlToLuceneQueryTranslator.java
+ *
+ * Created on October 31, 2006, 11:23 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.nescent.phylr.relational;
+
+import java.util.Properties;
+import org.oclc.os.SRW.SRWDiagnostic;
+import org.oclc.os.SRW.SortTool;
+import org.z3950.zing.cql.CQLNode;
+
+/**
+ *
+ * @author levan
+ */
+public interface CqlQueryTranslator {
+ void init(Properties properties, SRWRelationalDatabase ldb) throws
InstantiationException;
+
+ String makeQuery(CQLNode node, SortTool sortTool) throws SRWDiagnostic;
+
+}
Added:
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RecordResolver.java
==============================================================================
--- (empty file)
+++
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RecordResolver.java
Sun Jul 12 07:58:40 2009
@@ -0,0 +1,51 @@
+/*
+ * OCKHAM P2PREGISTRY Copyright 2006 Oregon State University
+ *
+ * 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 org.nescent.phylr.relational;
+
+import gov.loc.www.zing.srw.ExtraDataType;
+
+import java.sql.ResultSet;
+import java.util.Properties;
+import org.apache.lucene.document.Document;
+import org.oclc.os.SRW.Record;
+
+/**
+ * Interface for resolving records and schemas.
+ *
+ * @author peter
+ * Date: Oct 25, 2005
+ * Time: 9:49:08 AM
+ */
+public interface RecordResolver {
+
+ /**
+ * Resolves a record from the identifier
+ *
+ * @param Document - the document that Lucene has stored
+ * @param IdFieldName - the name of the field that contains the
identifier
+ * @param extraDataType - nonstandard SRW request parameters
+ * @return record if found.
+ */
+ public Record resolve(ResultSet hits, String IdFieldName,
ExtraDataType extraDataType);
+
+ /**
+ * Initialize the resolver.
+ *
+ * @param properties
+ */
+ public void init(Properties properties);
+}
Added:
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RelationalQueryResult.java
==============================================================================
--- (empty file)
+++
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RelationalQueryResult.java
Sun Jul 12 07:58:40 2009
@@ -0,0 +1,58 @@
+package org.nescent.phylr.relational;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import gov.loc.www.zing.srw.ExtraDataType;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.oclc.os.SRW.QueryResult;
+import org.oclc.os.SRW.RecordIterator;
+
+public class RelationalQueryResult extends QueryResult {
+ static final Log log=LogFactory.getLog(RelationalQueryResult.class);
+
+ ResultSet hits=null;
+ SRWRelationalDatabase ldb=null;
+ long count = -1;
+
+ /** Creates a new instance of LuceneQueryResult */
+ public RelationalQueryResult() {
+ }
+
+ /** Creates a new instance of LuceneQueryResult */
+ public RelationalQueryResult(SRWRelationalDatabase ldb, ResultSet
hits) {
+ this.ldb=ldb;
+ this.hits=hits;
+ }
+
+ @Override
+ public long getNumberOfRecords() {
+ if (count != -1)
+ return count;
+ if(hits==null) {
+ count = 0;
+ } else {
+ try {
+ hits.last();
+ count = hits.getRow();
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ return count;
+ }
+
+ @Override
+ public QueryResult getSortedResult(String sortKeys) {
+ return this;
+ }
+
+ @Override
+ public RecordIterator newRecordIterator(long whichRec, int numRecs,
+ String schemaId, ExtraDataType edt) throws InstantiationException {
+ log.debug("whichRec="+whichRec+", numRecs="+numRecs+",
schemaId="+schemaId+", edt="+edt);
+ return new RelationalRecordIterator(whichRec, schemaId, this,
(RecordResolver)ldb.resolvers.get(schemaId), edt);
+ }
+}
Added:
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RelationalRecordIterator.java
==============================================================================
--- (empty file)
+++
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/RelationalRecordIterator.java
Sun Jul 12 07:58:40 2009
@@ -0,0 +1,94 @@
+/**
+ * Copyright 2006 OCLC Online Computer Library Center, Inc.
+ *
+ * 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.
+ */
+/**
+ * LuceneRecordIterator.java
+ *
+ * Created on October 20, 2006, 3:03 PM
+ */
+
+package org.nescent.phylr.relational;
+
+import gov.loc.www.zing.srw.ExtraDataType;
+
+import java.sql.ResultSet;
+import java.util.NoSuchElementException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.oclc.os.SRW.Record;
+import org.oclc.os.SRW.RecordIterator;
+
+/**
+ *
+ * @author levan
+ */
+public class RelationalRecordIterator implements RecordIterator {
+ static final Log log=LogFactory.getLog(RelationalRecordIterator.class);
+
+ ExtraDataType edt;
+ int numRecs;
+ long whichRec;
+ RelationalQueryResult result;
+ RecordResolver resolver;
+ String schemaId;
+
+ /** Creates a new instance of LuceneRecordIterator */
+ public RelationalRecordIterator(long whichRec, String schemaId,
+ RelationalQueryResult result, RecordResolver resolver, ExtraDataType
edt) {
+ log.debug("whichRec="+whichRec+", schemaId="+schemaId+",
result="+result+", resolver="+resolver+", edt="+edt);
+ this.whichRec=whichRec;
+ this.schemaId=schemaId;
+ this.result=result;
+ this.resolver=resolver;
+ this.edt=edt;
+ }
+
+ public void close() {
+ try {
+ result.hits.close();
+ } catch (Exception ex) {}
+ }
+
+ public boolean hasNext() {
+ log.debug("whichRec="+whichRec+",
result.getNumberOfRecords()="+result.getNumberOfRecords());
+ if(whichRec<=result.getNumberOfRecords())
+ return true;
+ return false;
+ }
+
+ public Object next() throws NoSuchElementException {
+ return nextRecord();
+ }
+
+ public Record nextRecord() throws NoSuchElementException {
+ ResultSet hits = result.hits;
+ try {
+ hits.next();
+ return resolver.resolve(hits, result.ldb.idFieldName, edt);
+ }
+ catch(Exception e) {
+ log.error(e, e);
+ log.error("whichRec="+whichRec);
+ throw new NoSuchElementException(e.getMessage());
+ }
+ finally {
+ whichRec++;
+ }
+ }
+
+ public void remove() {
+ }
+}
Added:
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/SRWRelationalDatabase.java
==============================================================================
--- (empty file)
+++
trunk/phylr-gsoc/src/main/java/org/nescent/phylr/relational/SRWRelationalDatabase.java
Sun Jul 12 07:58:40 2009
@@ -0,0 +1,231 @@
+package org.nescent.phylr.relational;
+
+import gov.loc.www.zing.srw.ExtraDataType;
+import gov.loc.www.zing.srw.ScanRequestType;
+import gov.loc.www.zing.srw.SearchRetrieveRequestType;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.oclc.os.SRW.QueryResult;
+import org.oclc.os.SRW.Record;
+import org.oclc.os.SRW.SRWDatabase;
+import org.oclc.os.SRW.SRWDiagnostic;
+import org.oclc.os.SRW.SortTool;
+import org.oclc.os.SRW.TermList;
+import org.z3950.zing.cql.CQLNode;
+import org.z3950.zing.cql.CQLTermNode;
+
+public class SRWRelationalDatabase extends SRWDatabase {
+ static Log log = LogFactory.getLog(SRWRelationalDatabase.class);
+
+ CqlQueryTranslator translator = null;
+ // Hashtable indexSynonyms=new Hashtable();
+ Hashtable<String, RecordResolver> resolvers = new Hashtable<String,
RecordResolver>();
+ String idFieldName = null, indexInfo = null;
+
+ Connection connection = null;
+
+ @Override
+ public void addRenderer(String schemaName, String schemaID, Properties
props)
+ throws InstantiationException {
+ RecordResolver resolver = null;
+ String resolverName = dbProperties
+ .getProperty(schemaName + ".resolver");
+ if (resolverName == null) {
+ log.debug("creating BasicRelationalResolver");
+ resolver = new BasicRelationalRecordResolver();
+ resolver.init(props);
+ } else {
+ try {
+ log.debug("creating resolver " + resolverName);
+ Class resolverClass = Class.forName(resolverName);
+ log.debug("creating instance of class " + resolverClass);
+ resolver = (RecordResolver) resolverClass.newInstance();
+ resolver.init(dbProperties);
+ } catch (Exception e) {
+ log.error("Unable to create RecordResolver class "
+ + resolverName + " for database " + dbname);
+ log.error(e, e);
+ throw new InstantiationException(e.getMessage());
+ }
+ }
+ resolvers.put(schemaName, resolver);
+ resolvers.put(schemaID, resolver);
+ }
+
+ @Override
+ public String getExtraResponseData(QueryResult result,
+ SearchRetrieveRequestType request) {
+ return null;
+ }
+
+ @Override
+ public String getIndexInfo() {
+ if (indexInfo == null) {
+ // TODO: to implement
+ }
+ return indexInfo;
+ }
+
+ @Override
+ public QueryResult getQueryResult(String queryStr,
+ SearchRetrieveRequestType request) throws InstantiationException {
+ log.debug("entering SRWRelationalDatabase.getQueryResult");
+ ResultSet results = null;
+ Statement stmt = null;
+ try {
+ if (log.isDebugEnabled())
+ log.debug("query=" + queryStr);
+ CQLNode queryRoot = parser.parse(queryStr);
+
+ String sortKey = request.getSortKeys();
+ SortTool sortInfo = null;
+ if (sortKey != null && sortKey.length() > 0) {
+ log.info("sortKey=" + sortKey);
+ sortInfo = new SortTool(sortKey);
+ }
+
+ // convert the CQL search to lucene search
+ String query = translator.makeQuery(queryRoot, sortInfo);
+ log.info("lucene search=" + query);
+
+ // perform search
+ stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
+ ResultSet.CONCUR_READ_ONLY);
+
+ results = stmt.executeQuery(query);
+ return new RelationalQueryResult(this, results);
+ } catch (SRWDiagnostic e) {
+ RelationalQueryResult lqr = new RelationalQueryResult();
+ lqr.addDiagnostic(e.getCode(), e.getAddInfo());
+ return lqr;
+ } catch (Exception e) {
+ log.error(e, e);
+ RelationalQueryResult lqr = new RelationalQueryResult();
+ lqr.addDiagnostic(SRWDiagnostic.GeneralSystemError, e.getMessage());
+ return lqr;
+ } finally {
+ /*
+ if (results != null) {
+ try { results.close(); } catch (Exception ex) {}
+ }
+ if (stmt != null) {
+ try { stmt.close(); } catch (Exception ex) {}
+ }
+ */
+ }
+ }
+
+ @Override
+ public TermList getTermList(CQLTermNode cqlTermNode, int position,
+ int maxTerms, ScanRequestType scanRequestType) {
+ log.debug("in getTermList: cqlTermNode=" + cqlTermNode + ", position="
+ + position + ", maxTerms=" + maxTerms);
+ TermList list = new TermList();
+ if (position > 1) {
+ log.debug("unsupported responsePosition=" + position);
+ list.addDiagnostic(SRWDiagnostic.ResponsePositionOutOfRange,
+ Integer.toString(position));
+ } else {
+ // TODO: to implement
+ }
+ return list;
+ }
+
+ @Override
+ public boolean hasaConfigurationFile() {
+ return false; // a configuration file is not required
+ }
+
+ @Override
+ public void init(String dbname, String srwHome, String dbHome,
+ String dbPropertiesFileName, Properties dbProperties)
+ throws InstantiationException {
+ if (log.isDebugEnabled())
+ log.debug("entering SRWRelationalDatabase.init, dbname=" + dbname);
+
+ String xmlSchemaList = dbProperties.getProperty("xmlSchemas");
+ if (xmlSchemaList == null) {
+ log.info("No schemas specified in SRWDatabase.props ("
+ + dbPropertiesFileName + ")");
+ log
+ .info("The LuceneDocument schema will be automatically provided");
+ dbProperties.put("xmlSchemas", "LuceneDocument");
+ dbProperties.put("LuceneDocument.identifier",
+ "info:srw/schema/1/LuceneDocument");
+ dbProperties
+ .put("LuceneDocument.location",
+ "http://www.oclc.org/standards/Lucene/schema/LuceneDocument.xsd");
+ dbProperties.put("LuceneDocument.namespace",
+ "http://www.oclc.org/LuceneDocument");
+ dbProperties.put("LuceneDocument.title",
+ "Lucene records in their internal format");
+ }
+ super.initDB(dbname, srwHome, dbHome, dbPropertiesFileName,
+ dbProperties);
+
+ maxTerms = 10;
+ position = 1;
+
+ String url = dbProperties.getProperty("SRWRelationalDatabase.url");
+ log.debug("db url=" + url);
+
+ if (url == null) {
+ log.error("Database Connection URL not specified for database " +
dbname);
+ throw new InstantiationException("Database Connection URL not
specified");
+ }
+
+ try {
+ connection = DriverManager.getConnection(url);
+ } catch (Exception e) {
+ log.error("Unable to create connection with url=" + url
+ + " for database " + dbname);
+ log.error(e, e);
+ throw new InstantiationException(e.getMessage());
+ }
+
+ String translatorName = dbProperties.getProperty(
+ "SRWRelationalDatabase.CqlToSQLTranslator",
+ "org.nescent.phylr.relational.BasicSQLTranslator");
+ try {
+ log.debug("creating translator " + translatorName);
+ Class translatorClass = Class.forName(translatorName);
+ log.debug("creating instance of class " + translatorClass);
+ translator = (CqlQueryTranslator) translatorClass.newInstance();
+ translator.init(dbProperties, this);
+ } catch (Exception e) {
+ log.error("Unable to create CqlToLuceneQueryTranslator class "
+ + translatorName + " for database " + dbname);
+ log.error(e, e);
+ throw new InstantiationException(e.getMessage());
+ }
+ if (log.isDebugEnabled())
+ log.debug("leaving SRWLuceneDatabase.init");
+ }
+
+ /**
+ * Resolves a record from the identifier
+ *
+ * @param Id
+ * - identifier
+ * @param extraDataType
+ * - nonstandard search parameters
+ * @return record if found.
+ */
+ public Record resolve(String Id, ExtraDataType extraDataType) {
+ // need to create a resolver in the init step from config info
+ return null;
+ }
+
+ @Override
+ public boolean supportsSort() {
+ return true;
+ }
+}
\ No newline at end of file