001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021 022package org.biojavax.bio.db.biosql; 023import java.lang.reflect.Method; 024 025import org.biojava.bio.symbol.Alphabet; 026import org.biojava.bio.symbol.FiniteAlphabet; 027import org.biojava.bio.symbol.SymbolList; 028import org.biojavax.CrossRef; 029import org.biojavax.CrossReferenceResolver; 030import org.biojavax.Namespace; 031import org.biojavax.RichObjectFactory; 032import org.biojavax.SimpleNamespace; 033import org.biojavax.bio.BioEntry; 034import org.biojavax.bio.seq.InfinitelyAmbiguousSymbolList; 035import org.biojavax.bio.seq.RichSequence; 036 037/** 038 * A simple implementation of CrossReferenceResolver 039 * @author Richard Holland 040 * @author Mark Schreiber 041 * @author David Scott 042 * @since 1.5 043 */ 044public class BioSQLCrossReferenceResolver implements CrossReferenceResolver { 045 046 private Object session; 047 private Method createQuery; 048 private Method setParameter; 049 private Method uniqueResult; 050 051 /** 052 * Requires a Hibernate session to work correctly. The session parameter 053 * is a Hibernate Session object and must not be null. It is this session 054 * that database objects will be retrieved from/persisted to. 055 * @see <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html"> org.hibernate.Session</a> 056 */ 057 public BioSQLCrossReferenceResolver(Object session) { 058 try { 059 // Lazy load the Session class from Hibernate. 060 Class hibernateSession = session.getClass(); 061 Class realHibernateSession = Class.forName("org.hibernate.Session"); 062 // Test to see if our parameter is really a Session 063 if (!realHibernateSession.isAssignableFrom(hibernateSession)) 064 throw new IllegalArgumentException("Parameter must be a org.hibernate.Session object"); 065 this.session = session; 066 // Lookup the createQuery method 067 this.createQuery = hibernateSession.getMethod("createQuery", new Class[]{String.class}); 068 // Lazy load the Query class from Hibernate. 069 Class hibernateQuery = Class.forName("org.hibernate.Query"); 070 // Lookup the setParameter and uniqueQuery methods 071 this.setParameter = hibernateQuery.getMethod("setParameter", new Class[]{int.class,Object.class}); 072 this.uniqueResult = hibernateQuery.getMethod("uniqueResult", new Class[]{}); 073 } catch (ClassNotFoundException e) { 074 throw new RuntimeException(e); 075 } catch (NoSuchMethodException e) { 076 throw new RuntimeException(e); 077 } 078 } 079 080 /** 081 * {@inheritDoc} 082 */ 083 public SymbolList getRemoteSymbolList(CrossRef cr, Alphabet a) { 084 BioEntry be = this.getRemoteBioEntry(cr); 085 if (be instanceof RichSequence) return (RichSequence)be; 086 // If we get here we didn't find it, so we must create a dummy sequence instead 087 if (!(a instanceof FiniteAlphabet)) throw new IllegalArgumentException("Cannot construct dummy symbol list for a non-finite alphabet"); 088 return new InfinitelyAmbiguousSymbolList((FiniteAlphabet)a); 089 } 090 091 /** 092 * {@inheritDoc} 093 */ 094 public BioEntry getRemoteBioEntry(CrossRef cr){ 095 Namespace ns = (Namespace)RichObjectFactory.getObject(SimpleNamespace.class, new Object[]{cr.getDbname()}); 096 try { 097 // Build the query object 098 String queryText = "from BioEntry where namespace = ? and accession = ? and version = ?"; 099 Object query = this.createQuery.invoke(this.session, new Object[]{queryText}); 100 // Set the parameters 101 query = this.setParameter.invoke(query, new Object[]{new Integer(0), ns}); 102 query = this.setParameter.invoke(query, new Object[]{new Integer(1), cr.getAccession()}); 103 query = this.setParameter.invoke(query, new Object[]{new Integer(2), new Integer(cr.getVersion())}); 104 // Get the results 105 Object result = this.uniqueResult.invoke(query, (Object[])null); 106 // Return the found object, if found - null if not. 107 return (BioEntry)result; 108 } catch (Exception e) { 109 // Throw the exception with our nice message 110 throw new RuntimeException("Error while trying to locate remote cross reference "+cr,e); 111 } 112 } 113} 114