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;
024import java.util.HashSet;
025import java.util.Iterator;
026import java.util.List;
027import java.util.Set;
028
029import org.biojava.bio.BioException;
030import org.biojava.bio.seq.db.IllegalIDException;
031import org.biojava.utils.ChangeEvent;
032import org.biojava.utils.ChangeSupport;
033import org.biojava.utils.ChangeVetoException;
034import org.biojavax.bio.BioEntry;
035import org.biojavax.bio.db.AbstractBioEntryDB;
036import org.biojavax.bio.db.BioEntryDB;
037import org.biojavax.bio.db.BioEntryDBLite;
038import org.biojavax.bio.db.HashBioEntryDB;
039
040
041/**
042 *
043 * @author Richard Holland
044 * @author David Scott
045 * @since 1.5
046 */
047public class BioSQLBioEntryDB extends AbstractBioEntryDB {
048    
049    private Object session;
050    private String name;
051    
052    private Method createQuery;
053    private Method setParameter;
054    private Method list;
055    private Method delete;
056    private Method saveOrUpdate;
057    
058    /** Creates a new instance of BioSQLBioEntryDB */
059    public BioSQLBioEntryDB(Object session) {
060        this(null,session);
061    }
062    
063    /** Creates a new instance of BioSQLBioEntryDB */
064    public BioSQLBioEntryDB(String name, Object session) {
065        this.name = name;
066        this.session = session;
067        try {
068            // Lazy load the Session class from Hibernate.
069            Class hibernateSession = session.getClass();
070            Class realHibernateSession = Class.forName("org.hibernate.Session");
071            // Test to see if our parameter is really a Session
072            if (!realHibernateSession.isAssignableFrom(hibernateSession))
073                throw new IllegalArgumentException("Parameter must be a org.hibernate.Session object");
074            this.session = session;
075            // Lookup the createQuery method
076            this.createQuery = hibernateSession.getMethod("createQuery", new Class[]{String.class});
077            this.delete = hibernateSession.getMethod("delete", new Class[]{String.class,Object.class});
078            this.saveOrUpdate = hibernateSession.getMethod("saveOrUpdate", new Class[]{String.class,Object.class});
079            // Lazy load the Query class from Hibernate.
080            Class hibernateQuery = Class.forName("org.hibernate.Query");
081            // Lookup the setParameter and uniqueQuery methods
082            this.setParameter = hibernateQuery.getMethod("setParameter", new Class[]{int.class,Object.class});
083            this.list = hibernateQuery.getMethod("list", new Class[]{});
084        } catch (ClassNotFoundException e) {
085            throw new RuntimeException(e);
086        } catch (NoSuchMethodException e) {
087            throw new RuntimeException(e);
088        }
089    }
090    
091    public String getName() {
092        return this.name;
093    }
094    
095    public Object getHibernateSession() {
096        return this.session;
097    }
098    
099    public Set ids() {
100        try {
101            // Build the query object
102            String queryText = "select distinct name from BioEntry";
103            Object query = this.createQuery.invoke(this.session, new Object[]{queryText});
104            // Get the results
105            List result = (List)this.list.invoke(query, (Object[])null);
106            // Return the found object, if found - null if not.
107            return new HashSet(result);
108        } catch (Exception e) {
109            // Throw the exception with our nice message
110            throw new RuntimeException("Error while trying to load all names",e);
111        }
112    }
113    
114    public BioEntry getBioEntry(String id) throws IllegalIDException, BioException {
115        try {
116            // Build the query object
117            String queryText = "from BioEntry where name = ?";
118            Object query = this.createQuery.invoke(this.session, new Object[]{queryText});
119            // Set the parameters
120            query = this.setParameter.invoke(query, new Object[]{new Integer(0), id});
121            // Get the results
122            List result = (List)this.list.invoke(query, (Object[])null);
123            // If the result doesn't just have a single entry, throw an exception
124            if (result.size()==0) throw new IllegalIDException("Id not found: "+id);
125            else if (result.size()>1) throw new IllegalIDException("Multiple records found with that id - use getBioEntrys: "+id);
126            // Return the found object, if found - null if not.
127            return (BioEntry)result.get(0);
128        } catch (Exception e) {
129            // Throw the exception with our nice message
130            throw new RuntimeException("Error while trying to load by id: "+id,e);
131        }
132    }
133    
134    public BioEntryDB getBioEntrys(Set ids) throws BioException, IllegalIDException {
135        return this.getBioEntrys(ids,null);
136    }
137    
138    public BioEntryDB getBioEntrys(Set ids, BioEntryDB db) throws BioException, IllegalIDException {
139        if (db==null) db = new HashBioEntryDB();
140        try {
141            for (Iterator i = ids.iterator(); i.hasNext(); ) {
142                String id = (String)i.next();
143                // Build the query object
144                String queryText = "from BioEntry where name = ?";
145                Object query = this.createQuery.invoke(this.session, new Object[]{queryText});
146                // Set the parameters
147                query = this.setParameter.invoke(query, new Object[]{new Integer(0), id});
148                // Get the results
149                List result = (List)this.list.invoke(query, (Object[])null);
150                // If the result doesn't just have a single entry, throw an exception
151                if (result.size()==0) throw new IllegalIDException("Id not found: "+id);
152                // Add the results to the results db.
153                for (Iterator j = result.iterator(); j.hasNext(); ) db.addBioEntry((BioEntry)j.next());
154            }
155        } catch (Exception e) {
156            // Throw the exception with our nice message
157            throw new RuntimeException("Error while trying to load by ids: "+ids,e);
158        }
159        return db;
160    }
161    
162    public void removeBioEntry(String id) throws IllegalIDException, BioException, ChangeVetoException {
163        if(!hasListeners(BioEntryDBLite.BIOENTRYS)) {
164            this._removeBioEntry(id);
165        } else {
166            ChangeSupport changeSupport = getChangeSupport(BioEntryDBLite.BIOENTRYS);
167            synchronized(changeSupport) {
168                ChangeEvent ce = new ChangeEvent(
169                        this,
170                        BioEntryDBLite.BIOENTRYS,
171                        null,
172                        id
173                        );
174                changeSupport.firePreChangeEvent(ce);
175                this._removeBioEntry(id);
176                changeSupport.firePostChangeEvent(ce);
177            }
178        }
179    }
180    
181    private void _removeBioEntry(String id) throws IllegalIDException, BioException, ChangeVetoException {
182        try {
183            // Find the object
184            BioEntry be = this.getBioEntry(id);
185            // Get the results
186            this.delete.invoke(this.session, new Object[]{"BioEntry",be});
187        } catch (Exception e) {
188            // Throw the exception with our nice message
189            throw new RuntimeException("Error while trying to delete by id: "+id,e);
190        }
191    }
192    
193    public void addBioEntry(BioEntry seq) throws IllegalIDException, BioException, ChangeVetoException {
194        if(!hasListeners(BioEntryDBLite.BIOENTRYS)) {
195            this._addBioEntry(seq);
196        } else {
197            ChangeSupport changeSupport = getChangeSupport(BioEntryDBLite.BIOENTRYS);
198            synchronized(changeSupport) {
199                ChangeEvent ce = new ChangeEvent(
200                        this,
201                        BioEntryDBLite.BIOENTRYS,
202                        null,
203                        seq
204                        );
205                changeSupport.firePreChangeEvent(ce);
206                this._addBioEntry(seq);
207                changeSupport.firePostChangeEvent(ce);
208            }
209        }
210    }
211    
212    public void _addBioEntry(BioEntry seq) throws IllegalIDException, BioException, ChangeVetoException {
213        try {
214            // Get the results
215            this.saveOrUpdate.invoke(this.session, new Object[]{"BioEntry",seq});
216        } catch (Exception e) {
217            // Throw the exception with our nice message
218            throw new RuntimeException("Error while trying to save BioEntry with id: "+seq.getName(),e);
219        }
220    }
221    
222}