Changeset 408 for branches

Show
Ignore:
Timestamp:
06/11/10 19:05:19 (20 months ago)
Author:
bturner
Message:

Convert all db calls to follow canonical pattern of resource usage.

Location:
branches/ds_pool/src/org/bridgedb/rdb
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • branches/ds_pool/src/org/bridgedb/rdb/SimpleGdb.java

    r405 r408  
    1818 
    1919import java.sql.Connection; 
    20 import java.sql.DriverManager; 
    21 import java.sql.PreparedStatement; 
    2220import java.sql.ResultSet; 
    2321import java.sql.SQLException; 
    24  
     22import java.sql.Statement; 
     23 
     24import org.apache.commons.logging.Log; 
     25import org.apache.commons.logging.LogFactory; 
    2526import org.bridgedb.DataSource; 
    2627import org.bridgedb.IDMapperException; 
    2728 
    2829/** 
    29  * SimpleGdb is the main implementation of the Gdb interface, 
    30  * for dealing with single SQL-based pgdb's. 
    31  * It's responsible for creating and querying a single  
     30 * SimpleGdb is the main implementation of the Gdb interface, for dealing with 
     31 * single SQL-based pgdb's. It's responsible for creating and querying a single 
    3232 * pgdb relational database through the JDBC interface. 
    3333 * <p> 
    34  * It wraps SQL statements in methods,  
    35  * so the rest of the apps don't need to know the 
    36  * details of the Database schema. 
    37  * <p> 
    38  * It delegates dealing with the differences between  
    39  * various RDBMS's (Derby, Hsqldb etc.) 
    40  * to a DBConnector instance. 
    41  * A correct DBConnector instance needs to be  
    42  * passed to the constructor of SimpleGdb.  
    43  * <p> 
    44  * In the PathVisio GUI environment, use GdbManager 
    45  * to create and connect one or two centralized Gdb's.  
    46  * This will also automatically 
    47  * find the right DBConnector from the preferences. 
    48  * <p> 
    49  * In a head-less or test environment, you can bypass GdbManager 
    50  * and use SimpleGdb directly  
    51  * to create or connect to one or more pgdb's of any type. 
     34 * It wraps SQL statements in methods, so the rest of the apps don't need to 
     35 * know the details of the Database schema. 
     36 * <p> 
     37 * It delegates dealing with the differences between various RDBMS's (Derby, 
     38 * Hsqldb etc.) to a DBConnector instance. A correct DBConnector instance needs 
     39 * to be passed to the constructor of SimpleGdb. 
     40 * <p> 
     41 * In the PathVisio GUI environment, use GdbManager to create and connect one or 
     42 * two centralized Gdb's. This will also automatically find the right 
     43 * DBConnector from the preferences. 
     44 * <p> 
     45 * In a head-less or test environment, you can bypass GdbManager and use 
     46 * SimpleGdb directly to create or connect to one or more pgdb's of any type. 
    5247 */ 
    5348public abstract class SimpleGdb extends IDMapperRdb 
    5449{ 
    5550     
     51    private static final Log LOG = LogFactory.getLog(SimpleGdb.class); 
     52     
    5653    private JdbcConnectionPool pool; 
    5754     
    58      
    59         private final String connectionString; 
    60         /** 
    61          * Create IDMapper based on an existing SQL connection. 
    62          * @param con Existing SQL Connection. 
    63          */ 
    64         SimpleGdb(String dbName, String connectionString) 
    65         { 
    66                 this.connectionString = connectionString; 
    67                 this.dbName = dbName; 
    68                  
    69                 try 
    70         { 
    71                     // there's something a bit weird that this class does not know 
    72                     // it's underlying driver... 
    73                     String driverClassName = null; 
    74             pool = new JdbcConnectionPool(dbName, driverClassName, connectionString); 
     55    private boolean connected; 
     56     
     57    protected final String dbName; 
     58     
     59    /** 
     60     * Create IDMapper based on an existing SQL connection. 
     61     *  
     62     * @param data_ 
     63     *            .con Existing SQL Connection. 
     64     */ 
     65    SimpleGdb(String theDbName, 
     66              String connectionString) 
     67    { 
     68         
     69        dbName = theDbName; 
     70         
     71        try 
     72        { 
     73            // there's something a bit weird that this class does not know 
     74            // it's underlying driver... 
     75            String driverClassName = null; 
     76            pool = new JdbcConnectionPool(dbName, 
     77                                          driverClassName, 
     78                                          connectionString); 
     79            connected = true; 
    7580        } 
    7681        catch (IDMapperException e) 
     
    7883            throw new RuntimeException(e); 
    7984        } 
    80         } 
    81  
    82         private boolean singleConnection = true; 
    83         private boolean neverCloseConnection = true; 
    84          
    85         /** 
    86          * helper class that handles the life cycle of a connection, query and resultset. 
    87          * <p> 
    88          * The sql for a query is passed in at construction time. 
    89          * Before each query, call init(). This will lead to lazy initialization of the 
    90          * connection and preparedstatement objects, if necessary. Set the query parameters 
    91          * using setString(int, String). Get the resultSet using  
    92          * Do not close the resultset! This will be closed for you when you call cleanup(). 
    93          * Always call cleanup() in a finally block. 
    94          * <p> 
    95          * The advantages of using QueryLifeCycle are: 
    96          * <ul> 
    97          * <li>guarantee to close preparedstatement, resultset and connection if necessary. 
    98          * <li>in case of connection pooling, preparedstatement and connection are kept together as long 
    99          *   as possible. 
    100          * <li>lazy initialization of prepared statement 
    101          * <li>always uses preparedstatement, so safe from SQL injection. 
    102          * </ul>  
    103          * <p> 
    104          * This class is not static because it needs SimpleGdb.getConnection(). 
    105          */ 
    106         final class QueryLifeCycle 
    107         { 
    108                 /** 
    109                  * Initialize with given SQL string, but don't create PreparedStatement yet. 
    110                  * Valid to call before database connection is created. 
    111                  * @param aSql SQL query 
    112                  */ 
    113                 public QueryLifeCycle(String aSql) 
    114                 { 
    115                         sql = aSql; 
    116                 } 
    117                  
    118                 private Connection con = null; 
    119                 private ResultSet rs = null; 
    120                 private PreparedStatement pst = null; 
    121                 private final String sql; 
    122                 private boolean inited = false; 
    123  
    124                 public static final int QUERY_TIMEOUT = 20; //seconds 
    125                 public static final int NO_LIMIT = 0; 
    126                 public static final int NO_TIMEOUT = 0; 
    127  
    128                 public void init(int limit) throws SQLException 
    129                 { 
    130                         init(); 
    131                         pst.setQueryTimeout(QUERY_TIMEOUT);                      
    132                         if(limit > NO_LIMIT)  
    133                         { 
    134                                 pst.setMaxRows(limit); 
    135                         } 
    136                 } 
    137                  
    138                 /** 
    139                  * Initialize connection and PreparedStatement lazily. 
    140                  * <p> 
    141                  * @throws SQLException when a PreparedStatement could not be created 
    142                  */ 
    143                 public void init() throws SQLException 
    144                 { 
    145                         if (inited) throw new IllegalStateException("Must call cleanup() between two init() calls"); 
    146                         try 
    147                         { 
    148                                 if (con == null) con = getConnection(); 
    149                                 if (pst == null) 
    150                                 { 
    151                                         pst = con.prepareStatement(sql); 
    152                                 } 
    153                         } 
    154                         finally { inited = true; } 
    155                 } 
    156                  
    157                 public void setString (int index, String val) throws SQLException 
    158                 { 
    159                         if (!inited) throw new IllegalStateException("Must call init() before setString()"); 
    160                         pst.setString(index, val); 
    161                 } 
    162                  
    163                 public ResultSet executeQuery() throws SQLException 
    164                 { 
    165                         if (!inited) throw new IllegalStateException("Must call init() before executeQuery()"); 
    166                         rs = pst.executeQuery(); 
    167                         return rs; 
    168                 } 
    169  
    170                 /**  
    171                  * Clean up resultset. If keepConnection is false, preparedstatement 
    172                  * and connection are cached. If keepConnection is true, they are closed as well. 
    173                  * The later is useful when using connection pooling. 
    174                  * <p> 
    175                  * Always call this in a finally block!  
    176                  * */ 
    177                 public void cleanup() 
    178                 { 
    179                         if (!inited) throw new IllegalStateException("Must call init() before cleanup()"); 
    180                         inited = false; 
    181                         if (rs != null) try { rs.close(); } catch (SQLException ignore) {} 
    182                         if (neverCloseConnection) return; 
    183                         if (pst != null) try { pst.close(); } catch (SQLException ignore) {} 
    184                         pst = null; 
    185                         if (con != null) try { con.close(); } catch (SQLException ignore) {} 
    186                         con = null; 
    187                 } 
    188         } 
    189  
    190         private Connection con = null; 
    191          
    192         synchronized public Connection getConnection() throws SQLException 
    193         { 
    194             /* 
    195                 // if singleConnection is true, each call to getConnection() will return the same object. 
    196                 // if singleConnection is false, each call to getConneciton() will lead to a new connection object being created. 
    197                 if (!singleConnection || con == null) 
    198                 { 
    199                         con = DriverManager.getConnection(connectionString);  
    200                         con.setReadOnly(true); 
    201                 } 
    202                 return con; 
    203                 */ 
    204             return pool.getConnection(); 
    205         } 
    206          
    207         /** 
    208          * The {@link Connection} to the Gene Database. 
    209          */ 
    210          
    211         //private Connection con = null; 
    212  
    213         /** {@inheritDoc} */ 
    214         final public boolean isConnected() {  
    215                 //return con != null;  
    216                 return true; 
    217         } 
    218  
    219         protected final String dbName; 
    220          
    221         /** {@inheritDoc} */ 
    222         @Override final public String getDbName() { return dbName; } 
    223          
    224         /** {@inheritDoc} */ 
    225         final public void close() throws IDMapperException  
    226         { 
    227 //              try 
    228 //              { 
    229 //                      con.close(); 
    230 //              } 
    231 //              catch (SQLException ex) 
    232 //              { 
    233 //                      throw new IDMapperException (ex); 
    234 //              } 
    235 //              con = null; 
    236         } 
    237          
    238         public static final int NO_LIMIT = 0; 
    239         public static final int NO_TIMEOUT = 0; 
    240         public static final int QUERY_TIMEOUT = 5; //seconds 
    241  
    242         /** 
    243            @return number of rows in gene table. 
    244            @throws IDMapperException on failure 
    245          */ 
    246         final public int getGeneCount() throws IDMapperException 
    247         { 
    248                 int result = 0; 
    249                 try 
    250                 { 
    251                         ResultSet r = getConnection().createStatement().executeQuery("SELECT COUNT(*) FROM " + "datanode"); 
    252                         r.next(); 
    253                         result = r.getInt (1); 
    254                         r.close(); 
    255                 } 
    256                 catch (SQLException e) 
    257                 { 
    258                         throw new IDMapperException (e); 
    259                 } 
    260                 return result; 
    261         } 
    262  
    263         /** 
    264          * @param ds DataSource to count identifiers for. 
    265            @return number of identifiers table for the given datasource 
    266            @throws IDMapperException on failure 
    267          */ 
    268         final public int getGeneCount(DataSource ds) throws IDMapperException 
    269         { 
    270                 int result = 0; 
    271                 try 
    272                 { 
    273                         ResultSet r = getConnection().createStatement().executeQuery( 
    274                                         "SELECT COUNT(*) FROM datanode WHERE code = '" + ds.getSystemCode() + "'"); 
    275                         r.next(); 
    276                         result = r.getInt (1); 
    277                         r.close(); 
    278                 } 
    279                 catch (SQLException e) 
    280                 { 
    281                         throw new IDMapperException (e); 
    282                 } 
    283                 return result; 
    284         } 
    285          
     85    } 
     86     
     87    public Connection getConnection() throws SQLException 
     88    { 
     89         
     90        return pool.getConnection(); 
     91    } 
     92     
     93    /** {@inheritDoc} */ 
     94    @Override 
     95    final public String getDbName() 
     96    { 
     97        return dbName; 
     98    } 
     99     
     100    /** 
     101     * @return number of rows in gene table. 
     102     * @throws IDMapperException 
     103     *             on failure 
     104     */ 
     105    final public int getGeneCount() throws IDMapperException 
     106    { 
     107        int result = 0; 
     108         
     109        ResultSet r = null; 
     110        Statement s = null; 
     111        Connection c = null; 
     112        try 
     113        { 
     114            c = getConnection(); 
     115            s = c.createStatement(); 
     116            r = s.executeQuery("SELECT COUNT(*) FROM " 
     117                                                       + "datanode"); 
     118            r.next(); 
     119            result = r.getInt(1); 
     120        } 
     121        catch (SQLException e) 
     122        { 
     123            throw new IDMapperException(e); 
     124        } 
     125        finally 
     126        {    
     127            closeSilently(r, s, c); 
     128        } 
     129        return result; 
     130    } 
     131     
     132    /** 
     133     * @param ds 
     134     *            DataSource to count identifiers for. 
     135     * @return number of identifiers table for the given datasource 
     136     * @throws IDMapperException 
     137     *             on failure 
     138     */ 
     139    final public int getGeneCount(DataSource ds) throws IDMapperException 
     140    { 
     141        int result = 0; 
     142         
     143        ResultSet r = null; 
     144        Statement s = null; 
     145        Connection c = null; 
     146         
     147        try 
     148        { 
     149            c = getConnection(); 
     150            s = c.createStatement(); 
     151            r = s.executeQuery("SELECT COUNT(*) FROM datanode WHERE code = '" 
     152                               + ds.getSystemCode() + "'"); 
     153             
     154            r.next(); 
     155            result = r.getInt(1); 
     156        } 
     157        catch (SQLException e) 
     158        { 
     159            throw new IDMapperException(e); 
     160        } 
     161        finally 
     162        { 
     163            closeSilently(r, s, c); 
     164        } 
     165         
     166        return result; 
     167    } 
     168     
     169    protected void closeSilently(Connection c) 
     170    { 
     171        if (c != null) 
     172        { 
     173            try 
     174            { 
     175                c.close(); 
     176            } 
     177            catch (SQLException e) 
     178            { 
     179                LOG.error("Error closing result set: " + e, e); 
     180            } 
     181        } 
     182    } 
     183     
     184    protected void closeSilently(Statement s) 
     185    { 
     186        if (s != null) 
     187        { 
     188            try 
     189            { 
     190                s.close(); 
     191            } 
     192            catch (SQLException e) 
     193            { 
     194                LOG.error("Error closing statement: " + e, e); 
     195            } 
     196        } 
     197    } 
     198     
     199    protected void closeSilently(ResultSet rs) 
     200    { 
     201        if (rs != null) 
     202        { 
     203            try 
     204            { 
     205                rs.close(); 
     206            } 
     207            catch (SQLException e) 
     208            { 
     209                LOG.error("Error closing conection: " + e, e); 
     210            } 
     211        } 
     212    } 
     213     
     214    public void closeSilently(ResultSet r, 
     215                              Statement s, 
     216                              Connection c) 
     217    { 
     218         
     219        closeSilently(r); 
     220         
     221        closeSilently(s); 
     222         
     223        closeSilently(c); 
     224         
     225    } 
     226 
     227    @Override 
     228    public void close() throws IDMapperException 
     229    { 
     230        if (pool != null) 
     231        { 
     232             
     233            pool.shutdownDriver(); 
     234             
     235        } 
     236        connected = false; 
     237    } 
     238 
     239    @Override 
     240    public boolean isConnected() 
     241    { 
     242        
     243        return connected; 
     244    } 
     245     
     246     
    286247} 
  • branches/ds_pool/src/org/bridgedb/rdb/SimpleGdbFactory.java

    r405 r408  
    7777                finally 
    7878                { 
     79                    
    7980                        if (r != null) try { r.close(); } catch (SQLException ignore) {} 
    8081                        if (stmt != null) try { stmt.close(); } catch (SQLException ignore) {} 
  • branches/ds_pool/src/org/bridgedb/rdb/SimpleGdbImpl2.java

    r405 r408  
    1818 
    1919import java.sql.Connection; 
     20import java.sql.PreparedStatement; 
    2021import java.sql.ResultSet; 
    2122import java.sql.SQLException; 
     23import java.sql.Statement; 
    2224import java.util.HashMap; 
    2325import java.util.HashSet; 
     
    3234/** {@inheritDoc} */ 
    3335class SimpleGdbImpl2 extends SimpleGdbImplCommon 
    34 {                
    35         private static final int GDB_COMPAT_VERSION = 2; //Preferred schema version 
    36          
    37         private final SimpleGdb.QueryLifeCycle qBackpage = new SimpleGdb.QueryLifeCycle( 
    38                         "SELECT backpageText FROM datanode " + 
    39                         " WHERE id = ? AND code = ?" 
    40                 ); 
    41  
    42         /**  
    43          * get Backpage info. In Schema v2, this was not stored in  
    44          * the attribute table but as a separate column, so this is treated 
    45          * as a special case. This method is called by <pre>getAttribute (ref, "Backpage")</pre> 
    46          * @param ref the entity to get backpage info for. 
    47          * @return Backpage info as string 
    48          * @throws IDMapperException when database is unavailable 
    49          */ 
    50         private String getBpInfo(Xref ref) throws IDMapperException  
    51         { 
    52                 final QueryLifeCycle pst = qBackpage; 
    53                 synchronized (pst) 
    54                 { 
    55                         try { 
    56                                 pst.init(); 
    57                                 pst.setString (1, ref.getId()); 
    58                                 pst.setString (2, ref.getDataSource().getSystemCode()); 
    59                                 ResultSet r = pst.executeQuery(); 
    60                                 String result = null; 
    61                                 if (r.next()) 
    62                                 { 
    63                                         result = r.getString(1); 
    64                                 } 
    65                                 return result; 
    66                         } catch (SQLException e) { throw new IDMapperException (e); } //Gene not found 
    67                         finally {pst.cleanup(); } 
    68                 } 
    69         } 
    70  
    71         /** 
    72          * Opens a connection to the Gene Database located in the given file. 
    73          * A new instance of this class is created automatically. 
    74          * @param dbName The file containing the Gene Database.  
    75          * @param data_.con An existing SQL Connector. 
    76          * @param props PROP_RECREATE if you want to create a new database (possibly overwriting an existing one)  
    77          *      or PROP_NONE if you want to connect read-only 
    78          * @throws IDMapperException when the database could not be created or connected to 
    79          */ 
    80         public SimpleGdbImpl2(String dbName, String connectionString) throws IDMapperException 
    81         { 
    82                 super (dbName, connectionString); 
    83                  
    84                 if(dbName == null) throw new NullPointerException();             
    85                 checkSchemaVersion(); 
    86         } 
    87          
    88         /** 
    89          * look at the info table of the current database to determine the schema version. 
    90          * @throws IDMapperException when looking up the schema version failed 
    91          */ 
    92         private void checkSchemaVersion() throws IDMapperException  
    93         { 
    94                 int version = 0; 
    95                 try  
    96                 { 
    97                         ResultSet r = getConnection().createStatement().executeQuery("SELECT schemaversion FROM info"); 
    98                         if(r.next()) version = r.getInt(1); 
    99                 }  
    100                 catch (SQLException e)  
    101                 { 
    102                         //Ignore, older db's don't even have schema version 
    103                 } 
    104                 if(version != GDB_COMPAT_VERSION)  
    105                 { 
    106                         throw new IDMapperException ("Implementation and schema version mismatch"); 
    107                 } 
    108         } 
    109          
    110         private static final Map<String, String> ATTRIBUTES_FROM_BACKPAGE; 
    111          
    112         static 
    113         { 
    114                 ATTRIBUTES_FROM_BACKPAGE = new HashMap<String, String>(); 
    115                 ATTRIBUTES_FROM_BACKPAGE.put ("Chromosome", "<TH>Chr:<TH>([^<]*)<"); 
    116                 ATTRIBUTES_FROM_BACKPAGE.put ("Description", "<TH>Description:<TH>([^<]*)<"); 
    117                 ATTRIBUTES_FROM_BACKPAGE.put ("Synonyms", "<TH>Synonyms:<TH>([^<]*)<"); 
    118                 ATTRIBUTES_FROM_BACKPAGE.put ("Symbol", "<TH>(?:Gene Symbol|Metabolite):<TH>([^<]*)<"); 
    119                 ATTRIBUTES_FROM_BACKPAGE.put ("BrutoFormula", "<TH>Bruto Formula:<TH>([^<]*)<"); 
    120         } 
    121  
    122         /** {@inheritDoc} */ 
    123         public Set<String> getAttributes(Xref ref, String attrname) 
    124                         throws IDMapperException  
    125         { 
    126                 Set<String> result = new HashSet<String>(); 
    127                 final QueryLifeCycle pst = qAttribute; 
    128                  
    129                 if (ATTRIBUTES_FROM_BACKPAGE.containsKey(attrname)) 
    130                 { 
    131                         String bpInfo = getBpInfo(ref); 
    132                         if (bpInfo != null) 
    133                         { 
    134                                 Pattern pat = Pattern.compile(ATTRIBUTES_FROM_BACKPAGE.get (attrname)); 
    135                                 Matcher matcher = pat.matcher(bpInfo); 
    136                                 if (matcher.find()) 
    137                                 { 
    138                                         result.add (matcher.group(1)); 
    139                                 } 
    140                         } 
    141                 } 
    142                  
    143                 synchronized (pst) 
    144                 { 
    145                         try { 
    146                                 pst.init(); 
    147                                 pst.setString (1, ref.getId()); 
    148                                 pst.setString (2, ref.getDataSource().getSystemCode()); 
    149                                 pst.setString (3, attrname); 
    150                                 ResultSet r = pst.executeQuery(); 
    151                                 if (r.next()) 
    152                                 { 
    153                                         result.add (r.getString(1)); 
    154                                 } 
    155                                 return result; 
    156                         } catch (SQLException e) { throw new IDMapperException ("Xref:" + ref + ", Attribute: " + attrname, e); } // Database unavailable 
    157                         finally {pst.cleanup(); } 
    158                 } 
    159         } 
    160  
    161         /** {@inheritDoc} */ 
    162         public Map<String, Set<String>> getAttributes(Xref ref) 
    163                         throws IDMapperException  
    164         { 
    165                 Map<String, Set<String>> result = new HashMap<String, Set<String>>(); 
    166                 final QueryLifeCycle pst = qAllAttributes; 
    167                                  
    168                 String bpInfo = getBpInfo(ref); 
    169                 if (bpInfo != null) 
    170                 { 
    171                         for (String attrname : ATTRIBUTES_FROM_BACKPAGE.keySet()) 
    172                         { 
    173                                 Pattern pat = Pattern.compile(ATTRIBUTES_FROM_BACKPAGE.get (attrname)); 
    174                                 Matcher matcher = pat.matcher(bpInfo); 
    175                                 if (matcher.find()) 
    176                                 { 
    177                                         Set<String> attrSet = new HashSet<String>(); 
    178                                         attrSet.add (matcher.group(1)); 
    179                                         result.put (attrname, attrSet); 
    180                                 } 
    181                         } 
    182                 } 
    183                  
    184                 synchronized (pst) 
    185                 { 
    186                         try { 
    187                                 pst.init(); 
    188                                 pst.setString (1, ref.getId()); 
    189                                 pst.setString (2, ref.getDataSource().getSystemCode()); 
    190                                 ResultSet r = pst.executeQuery(); 
    191                                 if (r.next()) 
    192                                 { 
    193                                         String key = r.getString(1); 
    194                                         String value = r.getString(2); 
    195                                         if (result.containsKey (key)) 
    196                                         { 
    197                                                 result.get(key).add (value); 
    198                                         } 
    199                                         else 
    200                                         { 
    201                                                 Set<String> valueSet = new HashSet<String>(); 
    202                                                 valueSet.add (value); 
    203                                                 result.put (key, valueSet); 
    204                                         } 
    205                                 } 
    206                                 return result; 
    207                         } catch (SQLException e) { throw new IDMapperException ("Xref:" + ref, e); } // Database unavailable 
    208                         finally {pst.cleanup(); } 
    209                 } 
    210         } 
     36{ 
     37    private static final int GDB_COMPAT_VERSION = 2; // Preferred schema version 
     38     
     39    private final String qBackpage = "SELECT backpageText FROM datanode " 
     40                                              + " WHERE id = ? AND code = ?"; 
     41     
     42    /** 
     43     * get Backpage info. In Schema v2, this was not stored in the attribute 
     44     * table but as a separate column, so this is treated as a special case. 
     45     * This method is called by 
     46     *  
     47     * <pre> 
     48     * getAttribute(ref, &quot;Backpage&quot;) 
     49     * </pre> 
     50     *  
     51     * @param ref 
     52     *            the entity to get backpage info for. 
     53     * @return Backpage info as string 
     54     * @throws IDMapperException 
     55     *             when database is unavailable 
     56     */ 
     57    private String getBpInfo(Xref ref) throws IDMapperException 
     58    { 
     59        String result = null; 
     60        Connection c = null; 
     61        PreparedStatement pst = null; 
     62        ResultSet r = null; 
     63         
     64        try 
     65        { 
     66            c = getConnection(); 
     67            pst = c.prepareStatement(qBackpage); 
     68            pst.setString(1, ref.getId()); 
     69            pst.setString(2, ref.getDataSource().getSystemCode()); 
     70            r = pst.executeQuery(); 
     71             
     72            if (r.next()) 
     73            { 
     74                result = r.getString(1); 
     75            } 
     76             
     77        } 
     78        catch (SQLException e) 
     79        { 
     80            // Gene not found 
     81            throw new IDMapperException(e); 
     82        } 
     83        finally 
     84        { 
     85             
     86            closeSilently(r, pst, c); 
     87        } 
     88         
     89        return result; 
     90         
     91    } 
     92     
     93    /** 
     94     * Opens a connection to the Gene Database located in the given file. A new 
     95     * instance of this class is created automatically. 
     96     *  
     97     * @param dbName 
     98     *            The file containing the Gene Database. 
     99     * @param data_ 
     100     *            .con An existing SQL Connector. 
     101     * @param props 
     102     *            PROP_RECREATE if you want to create a new database (possibly 
     103     *            overwriting an existing one) or PROP_NONE if you want to 
     104     *            connect read-only 
     105     * @throws IDMapperException 
     106     *             when the database could not be created or connected to 
     107     */ 
     108    public SimpleGdbImpl2(String dbName, 
     109                          String connectionString) throws IDMapperException 
     110    { 
     111        super(dbName, connectionString); 
     112         
     113        if (dbName == null) 
     114            throw new NullPointerException(); 
     115        checkSchemaVersion(); 
     116    } 
     117     
     118    /** 
     119     * look at the info table of the current database to determine the schema 
     120     * version. 
     121     *  
     122     * @throws IDMapperException 
     123     *             when looking up the schema version failed 
     124     */ 
     125    private void checkSchemaVersion() throws IDMapperException 
     126    { 
     127        int version = 0; 
     128        Connection c = null; 
     129        Statement s = null; 
     130        ResultSet r = null; 
     131        try 
     132        { 
     133            c = getConnection(); 
     134            s = c.createStatement(); 
     135             
     136            r = s.executeQuery("SELECT schemaversion FROM info"); 
     137            if (r.next()) 
     138                version = r.getInt(1); 
     139        } 
     140        catch (SQLException e) 
     141        { 
     142            // Ignore, older db's don't even have schema version 
     143        } 
     144        finally 
     145        { 
     146            closeSilently(r, s, c); 
     147        } 
     148         
     149        if (version != GDB_COMPAT_VERSION) 
     150        { 
     151            throw new IDMapperException("Implementation and schema version mismatch"); 
     152        } 
     153    } 
     154     
     155    private static final Map<String, String> ATTRIBUTES_FROM_BACKPAGE; 
     156     
     157    static 
     158    { 
     159        ATTRIBUTES_FROM_BACKPAGE = new HashMap<String, String>(); 
     160        ATTRIBUTES_FROM_BACKPAGE.put("Chromosome", "<TH>Chr:<TH>([^<]*)<"); 
     161        ATTRIBUTES_FROM_BACKPAGE.put("Description", 
     162                                     "<TH>Description:<TH>([^<]*)<"); 
     163        ATTRIBUTES_FROM_BACKPAGE.put("Synonyms", "<TH>Synonyms:<TH>([^<]*)<"); 
     164        ATTRIBUTES_FROM_BACKPAGE.put("Symbol", 
     165                                     "<TH>(?:Gene Symbol|Metabolite):<TH>([^<]*)<"); 
     166        ATTRIBUTES_FROM_BACKPAGE.put("BrutoFormula", 
     167                                     "<TH>Bruto Formula:<TH>([^<]*)<"); 
     168    } 
     169     
     170    /** {@inheritDoc} */ 
     171    public Set<String> getAttributes(Xref ref, 
     172                                     String attrname) throws IDMapperException 
     173    { 
     174        Set<String> result = new HashSet<String>(); 
     175         
     176        if (ATTRIBUTES_FROM_BACKPAGE.containsKey(attrname)) 
     177        { 
     178            String bpInfo = getBpInfo(ref); 
     179            if (bpInfo != null) 
     180            { 
     181                Pattern pat = Pattern.compile(ATTRIBUTES_FROM_BACKPAGE.get(attrname)); 
     182                Matcher matcher = pat.matcher(bpInfo); 
     183                if (matcher.find()) 
     184                { 
     185                    result.add(matcher.group(1)); 
     186                } 
     187            } 
     188        } 
     189         
     190        Connection c = null; 
     191        PreparedStatement pst = null; 
     192        ResultSet r = null; 
     193        try 
     194        { 
     195            c = getConnection(); 
     196            pst = c.prepareStatement(qAttribute); 
     197             
     198            pst.setString(1, ref.getId()); 
     199            pst.setString(2, ref.getDataSource().getSystemCode()); 
     200            pst.setString(3, attrname); 
     201            r = pst.executeQuery(); 
     202            if (r.next()) 
     203            { 
     204                result.add(r.getString(1)); 
     205            } 
     206        } 
     207        catch (SQLException e) 
     208        { 
     209            throw new IDMapperException("Xref:" + ref + ", Attribute: " 
     210                                        + attrname, e); 
     211        } // Database unavailable 
     212        finally 
     213        { 
     214            closeSilently(r, pst, c); 
     215        } 
     216        return result; 
     217    } 
     218     
     219    /** {@inheritDoc} */ 
     220    public Map<String, Set<String>> getAttributes(Xref ref) throws IDMapperException 
     221    { 
     222        Map<String, Set<String>> result = new HashMap<String, Set<String>>(); 
     223         
     224        String bpInfo = getBpInfo(ref); 
     225        if (bpInfo != null) 
     226        { 
     227            for (String attrname : ATTRIBUTES_FROM_BACKPAGE.keySet()) 
     228            { 
     229                Pattern pat = Pattern.compile(ATTRIBUTES_FROM_BACKPAGE.get(attrname)); 
     230                Matcher matcher = pat.matcher(bpInfo); 
     231                if (matcher.find()) 
     232                { 
     233                    Set<String> attrSet = new HashSet<String>(); 
     234                    attrSet.add(matcher.group(1)); 
     235                    result.put(attrname, attrSet); 
     236                } 
     237            } 
     238        } 
     239        Connection c = null; 
     240        PreparedStatement pst = null; 
     241        ResultSet r = null; 
     242        try 
     243        { 
     244            c = getConnection(); 
     245            pst = c.prepareStatement(qAllAttributes); 
     246             
     247            pst.setString(1, ref.getId()); 
     248            pst.setString(2, ref.getDataSource().getSystemCode()); 
     249            r = pst.executeQuery(); 
     250            if (r.next()) 
     251            { 
     252                String key = r.getString(1); 
     253                String value = r.getString(2); 
     254                if (result.containsKey(key)) 
     255                { 
     256                    result.get(key).add(value); 
     257                } 
     258                else 
     259                { 
     260                    Set<String> valueSet = new HashSet<String>(); 
     261                    valueSet.add(value); 
     262                    result.put(key, valueSet); 
     263                } 
     264            } 
     265             
     266        } 
     267        catch (SQLException e) 
     268        { 
     269            throw new IDMapperException("Xref:" + ref, e); 
     270        } // Database unavailable 
     271        finally 
     272        { 
     273            closeSilently(r, pst, c); 
     274        } 
     275        return result; 
     276    } 
    211277} 
  • branches/ds_pool/src/org/bridgedb/rdb/SimpleGdbImpl3.java

    r405 r408  
    1818 
    1919import java.sql.Connection; 
     20import java.sql.PreparedStatement; 
    2021import java.sql.ResultSet; 
    2122import java.sql.SQLException; 
     23import java.sql.Statement; 
    2224import java.util.HashMap; 
    2325import java.util.HashSet; 
     
    3032/** {@inheritDoc} */ 
    3133class SimpleGdbImpl3 extends SimpleGdbImplCommon 
    32 {                
    33         private static final int GDB_COMPAT_VERSION = 3; //Preferred schema version 
    34  
    35         /** 
    36          * Opens a connection to the Gene Database located in the given file. 
    37          * A new instance of this class is created automatically. 
    38          * @param dbName The file containing the Gene Database.  
    39          * @param data_.con An existing java SQL connection 
    40          * @param props PROP_RECREATE if you want to create a new database (possibly overwriting an existing one)  
    41          *      or PROP_NONE if you want to connect read-only 
    42          * @throws IDMapperException when the database could not be created or connected to 
    43          */ 
    44         public SimpleGdbImpl3(String dbName, String connectionString) throws IDMapperException 
    45         { 
    46                 super(dbName, connectionString); 
    47                 checkSchemaVersion(); 
    48         } 
    49          
    50         /** 
    51          * look at the info table of the current database to determine the schema version. 
    52          * @throws IDMapperException when looking up the schema version failed 
    53          */ 
    54         private void checkSchemaVersion() throws IDMapperException  
    55         { 
    56                 int version = 0; 
    57                 try  
    58                 { 
    59                         ResultSet r = getConnection().createStatement().executeQuery("SELECT schemaversion FROM info"); 
    60                         if(r.next()) version = r.getInt(1); 
    61                 }  
    62                 catch (SQLException e)  
    63                 { 
    64                         //Ignore, older db's don't even have schema version 
    65                 } 
    66                 if(version != GDB_COMPAT_VERSION)  
    67                 { 
    68                         throw new IDMapperException ("Implementation and schema version mismatch"); 
    69                 } 
    70         } 
    71  
    72         /** {@inheritDoc} */ 
    73         public Set<String> getAttributes(Xref ref, String attrname) 
    74                         throws IDMapperException  
    75         { 
    76                 Set<String> result = new HashSet<String>(); 
    77                 final QueryLifeCycle pst = qAttribute; 
    78                 synchronized (pst) 
    79                 { 
    80                         try { 
    81                                 pst.init(); 
    82                                 pst.setString (1, ref.getId()); 
    83                                 pst.setString (2, ref.getDataSource().getSystemCode()); 
    84                                 pst.setString (3, attrname); 
    85                                 ResultSet r = pst.executeQuery(); 
    86                                 if (r.next()) 
    87                                 { 
    88                                         result.add (r.getString(1)); 
    89                                 } 
    90                                 return result; 
    91                         } catch (SQLException e) { throw new IDMapperException (e); } // Database unavailable 
    92                         finally {pst.cleanup(); } 
    93                 } 
    94         } 
    95  
    96         /** {@inheritDoc} */ 
    97         public Map<String, Set<String>> getAttributes(Xref ref) 
    98                         throws IDMapperException  
    99         { 
    100                 Map<String, Set<String>> result = new HashMap<String, Set<String>>();                            
    101                 final QueryLifeCycle pst = qAllAttributes; 
    102                 synchronized (pst) 
    103                 { 
    104                         try { 
    105                                 pst.init(); 
    106                                 pst.setString (1, ref.getId()); 
    107                                 pst.setString (2, ref.getDataSource().getSystemCode()); 
    108                                 ResultSet r = pst.executeQuery(); 
    109                                 while (r.next()) 
    110                                 { 
    111                                         String key = r.getString(1); 
    112                                         String value = r.getString(2); 
    113                                         if (result.containsKey (key)) 
    114                                         { 
    115                                                 result.get(key).add (value); 
    116                                         } 
    117                                         else 
    118                                         { 
    119                                                 Set<String> valueSet = new HashSet<String>(); 
    120                                                 valueSet.add (value); 
    121                                                 result.put (key, valueSet); 
    122                                         } 
    123                                 } 
    124                                 return result; 
    125                         } catch (SQLException e) { throw new IDMapperException ("Xref:" + ref, e); } // Database unavailable 
    126                         finally {pst.cleanup(); } 
    127                 } 
    128         } 
     34{ 
     35    private static final int GDB_COMPAT_VERSION = 3; // Preferred schema version 
     36     
     37    /** 
     38     * Opens a connection to the Gene Database located in the given file. A new 
     39     * instance of this class is created automatically. 
     40     *  
     41     * @param dbName 
     42     *            The file containing the Gene Database. 
     43     * @param data_ 
     44     *            .con An existing java SQL connection 
     45     * @param props 
     46     *            PROP_RECREATE if you want to create a new database (possibly 
     47     *            overwriting an existing one) or PROP_NONE if you want to 
     48     *            connect read-only 
     49     * @throws IDMapperException 
     50     *             when the database could not be created or connected to 
     51     */ 
     52    public SimpleGdbImpl3(String dbName, 
     53                          String connectionString) throws IDMapperException 
     54    { 
     55        super(dbName, connectionString); 
     56        checkSchemaVersion(); 
     57    } 
     58     
     59    /** 
     60     * look at the info table of the current database to determine the schema 
     61     * version. 
     62     *  
     63     * @throws IDMapperException 
     64     *             when looking up the schema version failed 
     65     */ 
     66    private void checkSchemaVersion() throws IDMapperException 
     67    { 
     68        int version = 0; 
     69        Connection c = null; 
     70        Statement s = null; 
     71        ResultSet r = null; 
     72        try 
     73        { 
     74            c = getConnection(); 
     75            s = c.createStatement(); 
     76             
     77           r = s.executeQuery("SELECT schemaversion FROM info"); 
     78            if (r.next()) 
     79                version = r.getInt(1); 
     80        } 
     81        catch (SQLException e) 
     82        { 
     83            // Ignore, older db's don't even have schema version 
     84        } 
     85        finally 
     86        { 
     87            closeSilently(r, s, c); 
     88        } 
     89        if (version != GDB_COMPAT_VERSION) 
     90        { 
     91            throw new IDMapperException("Implementation and schema version mismatch"); 
     92        } 
     93    } 
     94     
     95    /** {@inheritDoc} */ 
     96    public Set<String> getAttributes(Xref ref, 
     97                                     String attrname) throws IDMapperException 
     98    { 
     99        Set<String> result = new HashSet<String>(); 
     100         
     101        Connection c = null; 
     102        PreparedStatement pst = null; 
     103        ResultSet r = null; 
     104        try 
     105        { 
     106            c = getConnection(); 
     107            pst = c.prepareStatement(qAttribute); 
     108            pst.setString(1, ref.getId()); 
     109            pst.setString(2, ref.getDataSource().getSystemCode()); 
     110            pst.setString(3, attrname); 
     111            r = pst.executeQuery(); 
     112            if (r.next()) 
     113            { 
     114                result.add(r.getString(1)); 
     115            } 
     116             
     117        } 
     118        catch (SQLException e) 
     119        { 
     120            throw new IDMapperException(e); 
     121        } // Database unavailable 
     122        finally 
     123        { 
     124            closeSilently(r, pst, c); 
     125        } 
     126        return result; 
     127    } 
     128     
     129    /** {@inheritDoc} */ 
     130    public Map<String, Set<String>> getAttributes(Xref ref) throws IDMapperException 
     131    { 
     132        Map<String, Set<String>> result = new HashMap<String, Set<String>>(); 
     133         
     134        Connection c = null; 
     135        PreparedStatement pst = null; 
     136        ResultSet r = null; 
     137        try 
     138        { 
     139            c = getConnection(); 
     140            pst = c.prepareStatement(qAllAttributes); 
     141            pst.setString(1, ref.getId()); 
     142            pst.setString(2, ref.getDataSource().getSystemCode()); 
     143            r = pst.executeQuery(); 
     144            while (r.next()) 
     145            { 
     146                String key = r.getString(1); 
     147                String value = r.getString(2); 
     148                if (result.containsKey(key)) 
     149                { 
     150                    result.get(key).add(value); 
     151                } 
     152                else 
     153                { 
     154                    Set<String> valueSet = new HashSet<String>(); 
     155                    valueSet.add(value); 
     156                    result.put(key, valueSet); 
     157                } 
     158            } 
     159             
     160        } 
     161        catch (SQLException e) 
     162        { 
     163            throw new IDMapperException("Xref:" + ref, e); 
     164        } // Database unavailable 
     165        finally 
     166        { 
     167            closeSilently(r, pst, c); 
     168        } 
     169        return result; 
     170    } 
    129171} 
  • branches/ds_pool/src/org/bridgedb/rdb/SimpleGdbImplCommon.java

    r318 r408  
    11package org.bridgedb.rdb; 
    22 
     3import java.sql.Connection; 
     4import java.sql.PreparedStatement; 
    35import java.sql.ResultSet; 
    46import java.sql.ResultSetMetaData; 
     
    1921 
    2022/** 
    21  * Some methods and constants that are shared between SimpleGdbImpl2 and SimpleGdbImpl3 
     23 * Some methods and constants that are shared between SimpleGdbImpl2 and 
     24 * SimpleGdbImpl3 
    2225 */ 
    2326public abstract class SimpleGdbImplCommon extends SimpleGdb 
    2427{ 
    25         SimpleGdbImplCommon(String dbName, String connectionString) throws IDMapperException 
    26         { 
    27                 super(dbName, connectionString); 
    28                 caps = new SimpleGdbCapabilities(); 
    29         } 
    30  
    31         final SimpleGdb.QueryLifeCycle qDatasources = new SimpleGdb.QueryLifeCycle( 
    32                         "SELECT codeRight FROM link GROUP BY codeRight" 
    33                 ); 
    34         final SimpleGdb.QueryLifeCycle qInfo = new SimpleGdb.QueryLifeCycle( 
    35                         "SELECT * FROM info" 
    36                 ); 
    37         final SimpleGdb.QueryLifeCycle qXrefExists = new SimpleGdb.QueryLifeCycle( 
    38                         "SELECT id FROM " + "datanode" + " WHERE " + 
    39                         "id = ? AND code = ?" 
    40                 ); 
    41         final SimpleGdb.QueryLifeCycle qAttribute = new SimpleGdb.QueryLifeCycle( 
    42                         "SELECT attrvalue FROM attribute " + 
    43                         " WHERE id = ? AND code = ? AND attrname = ?" 
    44                 ); 
    45         final SimpleGdb.QueryLifeCycle qAllAttributes = new SimpleGdb.QueryLifeCycle( 
    46                         "SELECT attrname, attrvalue FROM attribute " + 
    47                         " WHERE id = ? AND code = ?" 
    48                 ); 
    49         final SimpleGdb.QueryLifeCycle qAttributesSet = new SimpleGdb.QueryLifeCycle( 
    50                         "SELECT attrname FROM attribute GROUP BY attrname" 
    51                 ); 
    52         final SimpleGdb.QueryLifeCycle qCrossRefs = new SimpleGdb.QueryLifeCycle ( 
    53                         "SELECT dest.idRight, dest.codeRight FROM link AS src JOIN link AS dest " + 
    54                         "ON src.idLeft = dest.idLeft and src.codeLeft = dest.codeLeft " + 
    55                         "WHERE src.idRight = ? AND src.codeRight = ?" 
    56                 ); 
    57         final SimpleGdb.QueryLifeCycle qCrossRefsWithCode = new SimpleGdb.QueryLifeCycle ( 
    58                         "SELECT dest.idRight, dest.codeRight FROM link AS src JOIN link AS dest " + 
    59                         "ON src.idLeft = dest.idLeft and src.codeLeft = dest.codeLeft " + 
    60                         "WHERE src.idRight = ? AND src.codeRight = ? AND dest.codeRight = ?" 
    61                 ); 
    62         final SimpleGdb.QueryLifeCycle qRefsByAttribute = new SimpleGdb.QueryLifeCycle ( 
    63                         "SELECT datanode.id, datanode.code FROM datanode " + 
    64                         " LEFT JOIN attribute ON attribute.code = datanode.code AND attribute.id = datanode.id " + 
    65                         "WHERE attrName = ? AND attrValue = ?" 
    66                 ); 
    67         final SimpleGdb.QueryLifeCycle qFreeSearch = new SimpleGdb.QueryLifeCycle ( 
    68                         "SELECT id, code FROM datanode WHERE " + 
    69                         "LOWER(ID) LIKE ?" 
    70                 ); 
    71         final SimpleGdb.QueryLifeCycle qAttributeSearch = new SimpleGdb.QueryLifeCycle ( 
    72                         "SELECT id, code, attrvalue FROM attribute WHERE " + 
    73                         "attrname = 'Symbol' AND LOWER(attrvalue) LIKE ?" 
    74                 ); 
    75         final SimpleGdb.QueryLifeCycle qIdSearchWithAttributes = new SimpleGdb.QueryLifeCycle ( 
    76                         "SELECT id, code, attrvalue FROM attribute WHERE " + 
    77                         "attrname = 'Symbol' AND LOWER(ID) LIKE ?" 
    78                 ); 
    79  
    80         /** {@inheritDoc} */ 
    81         public boolean xrefExists(Xref xref) throws IDMapperException  
    82         { 
    83                 final QueryLifeCycle pst = qXrefExists; 
    84                 synchronized (pst) { 
    85                         try  
    86                         { 
    87                                 pst.init(); 
    88                                 pst.setString(1, xref.getId()); 
    89                                 pst.setString(2, xref.getDataSource().getSystemCode()); 
    90                                 ResultSet r = pst.executeQuery(); 
    91          
    92                                 while(r.next())  
    93                                 { 
    94                                         return true; 
    95                                 } 
    96                         }  
    97                         catch (SQLException e)  
    98                         { 
    99                                 throw new IDMapperException (e); 
    100                         } 
    101                         finally {pst.cleanup(); } 
    102                         return false; 
    103                 } 
    104         } 
    105  
    106         /** 
    107          * Read the info table and return as properties. 
    108          * @return a map where keys are column names and values are the fields in the first row. 
    109          * @throws IDMapperException when the database became unavailable 
    110          */ 
    111         Map<String, String> getInfo() throws IDMapperException 
    112         { 
    113                 Map<String, String> result = new HashMap<String, String>(); 
    114                 final QueryLifeCycle pst = qInfo; 
    115                 synchronized (pst) { 
    116                         try 
    117                         { 
    118                                 pst.init(); 
    119                                 ResultSet rs = pst.executeQuery(); 
    120                                  
    121                                 if (rs.next()) 
    122                                 { 
    123                                         ResultSetMetaData rsmd = rs.getMetaData(); 
    124                                         for (int i = 1; i <= rsmd.getColumnCount(); ++i) 
    125                                         { 
    126                                                 String key = rsmd.getColumnName(i); 
    127                                                 String val = rs.getString(i); 
    128                                                 result.put (key, val); 
    129                                         } 
    130                                 } 
    131                         } 
    132                         catch (SQLException ex) 
    133                         { 
    134                                 throw new IDMapperException (ex); 
    135                         } 
    136                          
    137                         return result; 
    138                 } 
    139         } 
    140  
    141  
    142         /** {@inheritDoc} */ 
    143         public Set<Xref> mapID (Xref idc, DataSource... resultDs) throws IDMapperException 
    144         { 
    145                 final QueryLifeCycle pst = resultDs.length != 1 ? qCrossRefs : qCrossRefsWithCode; 
    146                 Set<Xref> refs = new HashSet<Xref>(); 
    147                  
    148                 if (idc.getDataSource() == null) return refs; 
    149                 synchronized (pst) { 
    150                         try 
    151                         { 
    152                                 pst.init(); 
    153                                 pst.setString(1, idc.getId()); 
    154                                 pst.setString(2, idc.getDataSource().getSystemCode()); 
    155                                 if (resultDs.length == 1) pst.setString(3, resultDs[0].getSystemCode());                         
    156                                  
    157                                 Set<DataSource> dsFilter = new HashSet<DataSource>(Arrays.asList(resultDs)); 
    158          
    159                                 ResultSet rs = pst.executeQuery(); 
    160                                 while (rs.next()) 
    161                                 { 
    162                                         DataSource ds = DataSource.getBySystemCode(rs.getString(2)); 
    163                                         if (resultDs.length == 0 || dsFilter.contains(ds)) 
    164                                         { 
    165                                                 refs.add (new Xref (rs.getString(1), ds)); 
    166                                         } 
    167                                 } 
    168                         } 
    169                         catch (SQLException e) 
    170                         { 
    171                                 throw new IDMapperException (e); 
    172                         } 
    173                         finally {pst.cleanup(); } 
    174                  
    175                         return refs; 
    176                 } 
    177         } 
    178  
    179         /** {@inheritDoc} */ 
    180         public List<Xref> getCrossRefsByAttribute(String attrName, String attrValue) throws IDMapperException { 
    181 //              Logger.log.trace("Fetching cross references by attribute: " + attrName + " = " + attrValue); 
    182                 List<Xref> refs = new ArrayList<Xref>(); 
    183  
    184                 final QueryLifeCycle pst = qRefsByAttribute; 
    185                 synchronized (pst) {  
    186                         try { 
    187                                 pst.init(); 
    188                                 pst.setString(1, attrName); 
    189                                 pst.setString(2, attrValue); 
    190                                 ResultSet r = pst.executeQuery(); 
    191                                 while(r.next()) { 
    192                                         Xref ref = new Xref(r.getString(1), DataSource.getBySystemCode(r.getString(2))); 
    193                                         refs.add(ref); 
    194                                 } 
    195                         } catch(SQLException e) { 
    196                                 throw new IDMapperException (e); 
    197                         } 
    198                         finally {pst.cleanup(); } 
    199         //              Logger.log.trace("End fetching cross references by attribute"); 
    200                         return refs; 
    201                 } 
    202         } 
    203  
    204         /** {@inheritDoc} */ 
    205         public Set<Xref> freeSearch (String text, int limit) throws IDMapperException  
    206         {                
    207                 Set<Xref> result = new HashSet<Xref>(); 
    208                 final QueryLifeCycle pst = qFreeSearch; 
    209                 synchronized (pst) {  
    210                         try { 
    211                                 pst.init(limit); 
    212                                 pst.setString(1, "%" + text.toLowerCase() + "%"); 
    213                                 ResultSet r = pst.executeQuery(); 
    214                                 while(r.next()) { 
    215                                         String id = r.getString(1); 
    216                                         DataSource ds = DataSource.getBySystemCode(r.getString(2)); 
    217                                         Xref ref = new Xref (id, ds); 
    218                                         result.add (ref); 
    219                                 }                        
    220                         }  
    221                         catch (SQLException e)  
    222                         { 
    223                                 throw new IDMapperException(e); 
    224                         } 
    225                         finally {pst.cleanup(); } 
    226                         return result; 
    227                 } 
    228         } 
    229  
    230         /** 
    231          * @return a list of data sources present in this database.  
    232            @throws IDMapperException when the database is unavailable 
    233          */ 
    234         private Set<DataSource> getDataSources() throws IDMapperException 
    235         { 
    236                 Set<DataSource> result = new HashSet<DataSource>(); 
    237                 final QueryLifeCycle pst = qDatasources; 
    238                 synchronized (pst) {  
    239                         try 
    240                 { 
    241                         pst.init(); 
    242                         ResultSet rs = pst.executeQuery(); 
    243                         while (rs.next()) 
    244                         { 
    245                                 DataSource ds = DataSource.getBySystemCode(rs.getString(1));  
    246                                 result.add (ds); 
    247                         } 
    248                 } 
    249                 catch (SQLException ignore) 
    250                 { 
    251                         throw new IDMapperException(ignore); 
    252                 } 
    253                         finally {pst.cleanup(); } 
    254                 return result; 
    255                 } 
    256         } 
    257  
    258         private final IDMapperCapabilities caps; 
    259  
    260         class SimpleGdbCapabilities extends AbstractIDMapperCapabilities 
    261         { 
    262                 /** default constructor. 
    263                  * @throws IDMapperException when database is not available */ 
    264                 public SimpleGdbCapabilities() throws IDMapperException  
    265                 { 
    266                         super (SimpleGdbImplCommon.this.getDataSources(), true,  
    267                                         SimpleGdbImplCommon.this.getInfo()); 
    268                 } 
    269         } 
    270  
    271         /** 
    272          * @return the capabilities of this gene database 
    273          */ 
    274         public IDMapperCapabilities getCapabilities()  
    275         { 
    276                 return caps; 
    277         } 
    278  
    279         /** 
    280          * 
    281          * @return true 
    282          */ 
    283         public boolean isFreeAttributeSearchSupported() 
    284         { 
    285                 return true; 
    286         } 
    287  
    288         /** 
    289          * free text search for matching symbols. 
    290          * @return references that match the query 
    291          * @param query The text to search for 
    292          * @param attrType the attribute to look for, e.g. 'Symbol' or 'Description'. 
    293          * @param limit The number of results to limit the search to 
    294          * @throws IDMapperException if the mapping service is (temporarily) unavailable  
    295          */ 
    296         public Map<Xref, String> freeAttributeSearch (String query, String attrType, int limit) throws IDMapperException 
    297         { 
    298                 Map<Xref, String> result = new HashMap<Xref, String>(); 
    299                 final QueryLifeCycle pst = (MATCH_ID.equals (attrType)) ?  
    300                                 qIdSearchWithAttributes : qAttributeSearch; 
    301                 synchronized (pst) {  
    302                         try { 
    303                                 pst.init(limit); 
    304                                 pst.setString(1, "%" + query.toLowerCase() + "%"); 
    305                                 ResultSet r = pst.executeQuery(); 
    306          
    307                                 while(r.next())  
    308                                 { 
    309                                         String id = r.getString("id"); 
    310                                         String code = r.getString("code"); 
    311                                         String symbol = r.getString("attrValue"); 
    312                                         result.put(new Xref (id, DataSource.getBySystemCode(code)), symbol); 
    313                                 } 
    314                         } catch (SQLException e) { 
    315                                 throw new IDMapperException (e); 
    316                         } 
    317                         finally {pst.cleanup(); } 
    318                         return result; 
    319                 } 
    320         } 
    321  
    322         /** {@inheritDoc} */ 
    323         public Set<String> getAttributeSet() throws IDMapperException  
    324         { 
    325                 Set<String> result = new HashSet<String>(); 
    326                 final QueryLifeCycle pst = qAttributesSet; 
    327                 synchronized (pst) {  
    328                 try 
    329                 { 
    330                         pst.init(); 
    331                         ResultSet rs = pst.executeQuery(); 
    332                         while (rs.next()) 
    333                         { 
    334                                 result.add (rs.getString(1)); 
    335                         } 
    336                 } 
    337                 catch (SQLException ignore) 
    338                 { 
    339                         throw new IDMapperException(ignore); 
    340                 } 
    341                         finally {pst.cleanup(); } 
    342                 return result; 
    343                 } 
    344         } 
    345  
     28    SimpleGdbImplCommon(String dbName, 
     29                        String connectionString) throws IDMapperException 
     30    { 
     31        super(dbName, connectionString); 
     32        caps = new SimpleGdbCapabilities(); 
     33    } 
     34     
     35    private final static String qDatasources = "SELECT codeRight FROM link GROUP BY codeRight"; 
     36     
     37    private final static String qInfo = "SELECT * FROM info"; 
     38     
     39    private final static String qXrefExists = "SELECT id FROM " 
     40                                                       + "datanode" + " WHERE " 
     41                                                       + "id = ? AND code = ?"; 
     42     
     43    protected final static String qAttribute = "SELECT attrvalue FROM attribute " 
     44                                                      + " WHERE id = ? AND code = ? AND attrname = ?"; 
     45     
     46    protected final static String qAllAttributes = "SELECT attrname, attrvalue FROM attribute " 
     47                                                          + " WHERE id = ? AND code = ?"; 
     48     
     49    private final static String qAttributesSet = "SELECT attrname FROM attribute GROUP BY attrname"; 
     50     
     51    private final static String qCrossRefs = "SELECT dest.idRight, dest.codeRight FROM link AS src JOIN link AS dest " 
     52                                                      + "ON src.idLeft = dest.idLeft and src.codeLeft = dest.codeLeft " 
     53                                                      + "WHERE src.idRight = ? AND src.codeRight = ?"; 
     54     
     55    private final static String qCrossRefsWithCode = "SELECT dest.idRight, dest.codeRight FROM link AS src JOIN link AS dest " 
     56                                                              + "ON src.idLeft = dest.idLeft and src.codeLeft = dest.codeLeft " 
     57                                                              + "WHERE src.idRight = ? AND src.codeRight = ? AND dest.codeRight = ?"; 
     58     
     59    private final static String qRefsByAttribute = "SELECT datanode.id, datanode.code FROM datanode " 
     60                                                            + " LEFT JOIN attribute ON attribute.code = datanode.code AND attribute.id = datanode.id " 
     61                                                            + "WHERE attrName = ? AND attrValue = ?"; 
     62     
     63    private final static String qFreeSearch = "SELECT id, code FROM datanode WHERE " 
     64                                                       + "LOWER(ID) LIKE ?"; 
     65     
     66    private final static String qAttributeSearch = "SELECT id, code, attrvalue FROM attribute WHERE " 
     67                                                            + "attrname = 'Symbol' AND LOWER(attrvalue) LIKE ?"; 
     68     
     69    private final static String qIdSearchWithAttributes = "SELECT id, code, attrvalue FROM attribute WHERE " 
     70                                                                   + "attrname = 'Symbol' AND LOWER(ID) LIKE ?"; 
     71     
     72    /** {@inheritDoc} */ 
     73    public boolean xrefExists(Xref xref) throws IDMapperException 
     74    { 
     75        Connection c = null; 
     76        PreparedStatement pst = null; 
     77        ResultSet r = null; 
     78        boolean exists = false; 
     79        try 
     80        { 
     81            c = getConnection(); 
     82            pst = c.prepareStatement(qXrefExists); 
     83             
     84            pst.setString(1, xref.getId()); 
     85            pst.setString(2, xref.getDataSource().getSystemCode()); 
     86            r = pst.executeQuery(); 
     87             
     88            exists = r.next(); 
     89             
     90        } 
     91        catch (SQLException e) 
     92        { 
     93            throw new IDMapperException(e); 
     94        } 
     95        finally 
     96        { 
     97            closeSilently(r, pst, c); 
     98        } 
     99        return exists; 
     100    } 
     101     
     102    /** 
     103     * Read the info table and return as properties. 
     104     *  
     105     * @return a map where keys are column names and values are the fields in 
     106     *         the first row. 
     107     * @throws IDMapperException 
     108     *             when the database became unavailable 
     109     */ 
     110    Map<String, String> getInfo() throws IDMapperException 
     111    { 
     112        Map<String, String> result = new HashMap<String, String>(); 
     113         
     114        Connection c = null; 
     115        PreparedStatement pst = null; 
     116        ResultSet r = null; 
     117        try 
     118        { 
     119            c = getConnection(); 
     120            pst = c.prepareStatement(qInfo); 
     121             
     122            r = pst.executeQuery(); 
     123             
     124            if (r.next()) 
     125            { 
     126                ResultSetMetaData rsmd = r.getMetaData(); 
     127                for (int i = 1; i <= rsmd.getColumnCount(); ++i) 
     128                { 
     129                    String key = rsmd.getColumnName(i); 
     130                    String val = r.getString(i); 
     131                    result.put(key, val); 
     132                } 
     133            } 
     134        } 
     135        catch (SQLException ex) 
     136        { 
     137            throw new IDMapperException(ex); 
     138        } 
     139        finally 
     140        { 
     141            closeSilently(r, pst, c); 
     142        } 
     143         
     144        return result; 
     145         
     146    } 
     147     
     148    /** {@inheritDoc} */ 
     149    public Set<Xref> mapID(Xref idc, 
     150                           DataSource... resultDs) throws IDMapperException 
     151    { 
     152        String query = resultDs.length != 1 ? qCrossRefs : qCrossRefsWithCode; 
     153        Set<Xref> refs = new HashSet<Xref>(); 
     154         
     155        if (idc.getDataSource() != null) 
     156        { 
     157             
     158            Connection c = null; 
     159            PreparedStatement pst = null; 
     160            ResultSet rs = null; 
     161            try 
     162            { 
     163                c = getConnection(); 
     164                pst =c.prepareStatement(query); 
     165                 
     166                pst.setString(1, idc.getId()); 
     167                pst.setString(2, idc.getDataSource().getSystemCode()); 
     168                if (resultDs.length == 1) 
     169                    pst.setString(3, resultDs[0].getSystemCode()); 
     170                 
     171                Set<DataSource> dsFilter = new HashSet<DataSource>(Arrays.asList(resultDs)); 
     172                 
     173                rs = pst.executeQuery(); 
     174                while (rs.next()) 
     175                { 
     176                    DataSource ds = DataSource.getBySystemCode(rs.getString(2)); 
     177                    if (resultDs.length == 0 || dsFilter.contains(ds)) 
     178                    { 
     179                        refs.add(new Xref(rs.getString(1), ds)); 
     180                    } 
     181                } 
     182            } 
     183            catch (SQLException e) 
     184            { 
     185                throw new IDMapperException(e); 
     186            } 
     187            finally 
     188            { 
     189                closeSilently(rs, pst, c); 
     190            } 
     191        } 
     192        return refs; 
     193         
     194    } 
     195     
     196    /** {@inheritDoc} */ 
     197    public List<Xref> getCrossRefsByAttribute(String attrName, 
     198                                              String attrValue) throws IDMapperException 
     199    { 
     200        // Logger.log.trace("Fetching cross references by attribute: " + 
     201        // attrName + " = " + attrValue); 
     202        List<Xref> refs = new ArrayList<Xref>(); 
     203         
     204        Connection c = null; 
     205        PreparedStatement pst = null; 
     206        ResultSet r = null; 
     207         
     208        try 
     209        { 
     210            c = getConnection(); 
     211            pst = c.prepareStatement(qRefsByAttribute); 
     212             
     213            pst.setString(1, attrName); 
     214            pst.setString(2, attrValue); 
     215            r = pst.executeQuery(); 
     216            while (r.next()) 
     217            { 
     218                Xref ref = new Xref(r.getString(1), 
     219                                    DataSource.getBySystemCode(r.getString(2))); 
     220                refs.add(ref); 
     221            } 
     222        } 
     223        catch (SQLException e) 
     224        { 
     225            throw new IDMapperException(e); 
     226        } 
     227        finally 
     228        { 
     229            closeSilently(r, pst, c); 
     230        } 
     231        // Logger.log.trace("End fetching cross references by attribute"); 
     232        return refs; 
     233         
     234    } 
     235     
     236    /** {@inheritDoc} */ 
     237    public Set<Xref> freeSearch(String text, 
     238                                int limit) throws IDMapperException 
     239    { 
     240        Set<Xref> result = new HashSet<Xref>(); 
     241         
     242        Connection c = null; 
     243        PreparedStatement pst = null; 
     244        ResultSet r = null; 
     245         
     246        try 
     247        { 
     248            c = getConnection(); 
     249            pst = c.prepareStatement(qFreeSearch); 
     250            pst.setString(1, "%" + text.toLowerCase() + "%"); 
     251            r = pst.executeQuery(); 
     252            while (r.next()) 
     253            { 
     254                String id = r.getString(1); 
     255                DataSource ds = DataSource.getBySystemCode(r.getString(2)); 
     256                Xref ref = new Xref(id, ds); 
     257                result.add(ref); 
     258            } 
     259        } 
     260        catch (SQLException e) 
     261        { 
     262            throw new IDMapperException(e); 
     263        } 
     264        finally 
     265        { 
     266            closeSilently(r, pst, c); 
     267        } 
     268        return result; 
     269         
     270    } 
     271     
     272    /** 
     273     * @return a list of data sources present in this database. 
     274     * @throws IDMapperException 
     275     *             when the database is unavailable 
     276     */ 
     277    private Set<DataSource> getDataSources() throws IDMapperException 
     278    { 
     279        Set<DataSource> result = new HashSet<DataSource>(); 
     280         
     281        Connection c = null; 
     282        PreparedStatement pst = null; 
     283        ResultSet rs = null; 
     284         
     285        try 
     286        { 
     287            c = getConnection(); 
     288            pst = c.prepareStatement(qDatasources); 
     289            rs = pst.executeQuery(); 
     290            while (rs.next()) 
     291            { 
     292                DataSource ds = DataSource.getBySystemCode(rs.getString(1)); 
     293                result.add(ds); 
     294            } 
     295        } 
     296        catch (SQLException e) 
     297        { 
     298            throw new IDMapperException(e); 
     299        } 
     300        finally 
     301        { 
     302            closeSilently(rs, pst, c); 
     303        } 
     304        return result; 
     305         
     306    } 
     307     
     308    private final IDMapperCapabilities caps; 
     309     
     310    class SimpleGdbCapabilities extends AbstractIDMapperCapabilities 
     311    { 
     312        /** 
     313         * default constructor. 
     314         *  
     315         * @throws IDMapperException 
     316         *             when database is not available 
     317         */ 
     318        public SimpleGdbCapabilities() throws IDMapperException 
     319        { 
     320            super(SimpleGdbImplCommon.this.getDataSources(), 
     321                  true, 
     322                  SimpleGdbImplCommon.this.getInfo()); 
     323        } 
     324    } 
     325     
     326    /** 
     327     * @return the capabilities of this gene database 
     328     */ 
     329    public IDMapperCapabilities getCapabilities() 
     330    { 
     331        return caps; 
     332    } 
     333     
     334    /** 
     335     *  
     336     * @return true 
     337     */ 
     338    public boolean isFreeAttributeSearchSupported() 
     339    { 
     340        return true; 
     341    } 
     342     
     343    /** 
     344     * free text search for matching symbols. 
     345     *  
     346     * @return references that match the query 
     347     * @param query 
     348     *            The text to search for 
     349     * @param attrType 
     350     *            the attribute to look for, e.g. 'Symbol' or 'Description'. 
     351     * @param limit 
     352     *            The number of results to limit the search to 
     353     * @throws IDMapperException 
     354     *             if the mapping service is (temporarily) unavailable 
     355     */ 
     356    public Map<Xref, String> freeAttributeSearch(String query, 
     357                                                 String attrType, 
     358                                                 int limit) throws IDMapperException 
     359    { 
     360        Map<Xref, String> result = new HashMap<Xref, String>(); 
     361        String querySql = (MATCH_ID.equals(attrType)) ? qIdSearchWithAttributes 
     362                : qAttributeSearch; 
     363         
     364        Connection c = null; 
     365        PreparedStatement pst = null; 
     366        ResultSet r = null; 
     367         
     368        try 
     369        { 
     370            c = getConnection(); 
     371            pst = c.prepareStatement(querySql); 
     372            pst.setString(1, "%" + query.toLowerCase() + "%"); 
     373            r = pst.executeQuery(); 
     374             
     375            while (r.next()) 
     376            { 
     377                String id = r.getString("id"); 
     378                String code = r.getString("code"); 
     379                String symbol = r.getString("attrValue"); 
     380                result.put(new Xref(id, DataSource.getBySystemCode(code)), 
     381                           symbol); 
     382            } 
     383        } 
     384        catch (SQLException e) 
     385        { 
     386            throw new IDMapperException(e); 
     387        } 
     388        finally 
     389        { 
     390            closeSilently(r, pst, c); 
     391        } 
     392        return result; 
     393         
     394    } 
     395     
     396    /** {@inheritDoc} */ 
     397    public Set<String> getAttributeSet() throws IDMapperException 
     398    { 
     399        Set<String> result = new HashSet<String>(); 
     400         
     401        Connection c = null; 
     402        PreparedStatement pst = null; 
     403        ResultSet rs = null; 
     404         
     405        try 
     406        { 
     407            c = getConnection(); 
     408            pst = c.prepareStatement(qAttributesSet); 
     409            rs = pst.executeQuery(); 
     410            while (rs.next()) 
     411            { 
     412                result.add(rs.getString(1)); 
     413            } 
     414        } 
     415        catch (SQLException ignore) 
     416        { 
     417            throw new IDMapperException(ignore); 
     418        } 
     419        finally 
     420        { 
     421            closeSilently(rs, pst, c); 
     422        } 
     423        return result; 
     424    } 
     425     
    346426}