Coverage Report - uk.ac.ebi.intenz.mapper.EnzymeReactionMapper
 
Classes in this File Line Coverage Branch Coverage Complexity
EnzymeReactionMapper
73%
79/108
45%
27/60
3.846
 
 1  
 package uk.ac.ebi.intenz.mapper;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.sql.Connection;
 5  
 import java.sql.PreparedStatement;
 6  
 import java.sql.ResultSet;
 7  
 import java.sql.SQLException;
 8  
 
 9  
 import org.apache.log4j.Logger;
 10  
 
 11  
 import uk.ac.ebi.intenz.domain.constants.EnzymeViewConstant;
 12  
 import uk.ac.ebi.intenz.domain.enzyme.EnzymaticReactions;
 13  
 import uk.ac.ebi.rhea.domain.Database;
 14  
 import uk.ac.ebi.rhea.domain.Reaction;
 15  
 import uk.ac.ebi.rhea.domain.Status;
 16  
 import uk.ac.ebi.rhea.mapper.MapperException;
 17  
 import uk.ac.ebi.rhea.mapper.db.RheaCompoundDbReader;
 18  
 import uk.ac.ebi.rhea.mapper.db.RheaDbReader;
 19  
 
 20  
 /**
 21  
  * Maps reaction information to the corresponding database table.
 22  
  * <br>
 23  
  * <b>IMPORTANT</b>: after using instances of this class, call the
 24  
  * {@link #close()} method, otherwise the underlying Rhea mapper objects will
 25  
  * keep their statements open.
 26  
  * @author Michael Darsow,
 27  
  *                 Rafael Alcántara
 28  
  * @version $Revision: 1.6 $ $Date: 2009/05/26 14:59:09 $
 29  
  */
 30  1
 public class EnzymeReactionMapper {
 31  
 
 32  1
         private static final Logger LOGGER =
 33  
                 Logger.getLogger(EnzymeReactionMapper.class.getName());
 34  
         
 35  
         protected RheaDbReader rheaReader;
 36  
         
 37  13
   public EnzymeReactionMapper(){
 38  
           try {
 39  13
                 rheaReader = new RheaDbReader(
 40  
                         new RheaCompoundDbReader((Connection) null));
 41  0
         } catch (IOException e) {
 42  0
                 throw new RuntimeException(e);
 43  13
         }
 44  13
   }
 45  
 
 46  
   private static final String SEL_COLS_FROM_TBLS =
 47  
           "SELECT rm.reaction_id, rm.web_view, rm.order_in, rm.iubmb," +
 48  
           " ir.equation, ir.source, ir.qualifiers, ir.status" +
 49  
           " FROM reactions_map rm, intenz_reactions ir";
 50  
 
 51  
   private static final String FIND_STM =
 52  
           SEL_COLS_FROM_TBLS +
 53  
           " WHERE rm.enzyme_id = ? AND rm.reaction_id = ir.reaction_id" +
 54  
           " ORDER BY rm.order_in";
 55  
 
 56  
   private static final String FIND_SIB_STM =
 57  
           SEL_COLS_FROM_TBLS +
 58  
         " WHERE rm.enzyme_id = ? AND rm.reaction_id = ir.reaction_id" +
 59  
         " AND (rm.web_view  LIKE '%SIB%' OR rm.web_view = 'INTENZ')" +
 60  
         " ORDER BY rm.order_in";
 61  
 
 62  
   private static final String INSERT_STM =
 63  
           "INSERT INTO reactions_map (reaction_id, enzyme_id, web_view, iubmb," +
 64  
           " order_in) VALUES (?, ?, ?, ?, ?)";
 65  
 
 66  
   private static final String DELETE_ALL_STM =
 67  
           "DELETE reactions_map WHERE enzyme_id = ?";
 68  
 
 69  
   /* Abstract reactions in old REACTIONS table */
 70  
   
 71  
         private static final String SEL_ABSTRACT_COLS_FROM_TBLS =
 72  
                 "SELECT equation, web_view, order_in, source, NULL reaction_id," +
 73  
                 " 'N' iubmb, NULL qualifiers, status FROM reactions";
 74  
 
 75  
         private static final String FIND_ABSTRACT_STM =
 76  
                 SEL_ABSTRACT_COLS_FROM_TBLS +
 77  
                 " WHERE enzyme_id = ? ORDER BY order_in";
 78  
 
 79  
         private static final String FIND_ABSTRACT_SIB_STM =
 80  
                 SEL_ABSTRACT_COLS_FROM_TBLS + " WHERE enzyme_id = ? AND" +
 81  
                 " (web_view LIKE '%SIB%' OR web_view = 'INTENZ') ORDER BY order_in";
 82  
 
 83  
         private static final String INSERT_ABSTRACT_STM =
 84  
                 "INSERT INTO reactions (enzyme_id, equation, order_in, status, source," +
 85  
                 " web_view) VALUES (?, ?, ?, ?, ?, ?)";
 86  
 
 87  
   private static final String DELETE_ALL_ABSTRACT_STM =
 88  
           "DELETE reactions WHERE enzyme_id = ?";
 89  
 
 90  
   /**
 91  
    * Tries to find reaction information about an enzyme.
 92  
    *
 93  
    * @param enzymeId Enzyme ID of entry.
 94  
    * @param con      The logical connection.
 95  
    * @return a <code>EnzymaticReactions</code> object containing
 96  
    *         <code>Reaction</code>instances or <code>null</code> if nothing has been found.
 97  
    * @throws SQLException in case of a generic database problem.
 98  
    * @throws MapperException in case of problem retrieving Rhea reactions.
 99  
    */
 100  
   public EnzymaticReactions find(Long enzymeId, Connection con)
 101  
   throws SQLException, MapperException {
 102  2
         if (enzymeId == null) {
 103  0
             throw new NullPointerException("Parameter 'enzymeId' must not be null.");
 104  
         }
 105  2
         if (con == null) {
 106  0
             throw new NullPointerException("Parameter 'con' must not be null.");
 107  
         }
 108  
 
 109  2
         EnzymaticReactions result = find(enzymeId, con, FIND_STM);
 110  2
             EnzymaticReactions abstractReactions =
 111  
                     find(enzymeId, con, FIND_ABSTRACT_STM);
 112  2
         if (result == null) { // no Rhea reactions
 113  1
             result = abstractReactions;
 114  
         } else {
 115  1
                 if (abstractReactions != null) result.add(abstractReactions);
 116  
         }
 117  2
         return result;
 118  
     }
 119  
 
 120  
   /**
 121  
    * Exports all reactions which are displayed in the ENZYME view.
 122  
    *
 123  
    * Affected table rows will be locked.
 124  
    *
 125  
    * @param enzymeId The enzyme ID used to retreive the related reactions.
 126  
    * @param con The database connection.
 127  
    * @return an <code>EnzymaticReactions</code> containing reactions
 128  
    *         or <code>null</code> if no reaction could be found.
 129  
    * @throws SQLException if a generic database error occured.
 130  
    * @throws MapperException in case of problem retrieving Rhea reactions.
 131  
    * @throws NullPointerException if either of the parameters is <code>null</code>.
 132  
    */
 133  
   public EnzymaticReactions exportSibReactions(Long enzymeId, Connection con)
 134  
   throws SQLException, MapperException {
 135  0
     if (enzymeId == null) throw new NullPointerException("Parameter 'enzymeId' must not be null.");
 136  0
     if (con == null) throw new NullPointerException("Parameter 'con' must not be null.");
 137  
 
 138  0
     EnzymaticReactions result = find(enzymeId, con, FIND_SIB_STM);
 139  0
     if (result == null)
 140  0
             result = find(enzymeId, con, FIND_ABSTRACT_SIB_STM);
 141  
     else
 142  0
         result.add(find(enzymeId, con, FIND_ABSTRACT_SIB_STM));
 143  0
     return result;
 144  
   }
 145  
   
 146  
   private EnzymaticReactions find(Long enzymeId, Connection con,
 147  
                   String findQuery)
 148  
   throws SQLException, MapperException {
 149  4
           EnzymaticReactions result = null;
 150  4
           PreparedStatement findStatement = null;
 151  4
           ResultSet rs = null;
 152  
           try {
 153  4
                   findStatement = con.prepareStatement(findQuery);
 154  4
                   findStatement.setLong(1, enzymeId.longValue());
 155  4
                   rs = findStatement.executeQuery();
 156  9
                   while (rs.next()) {
 157  5
                           if (result == null) result = new EnzymaticReactions();
 158  5
               result.add(loadReaction(rs), rs.getString("web_view"),
 159  
                               rs.getString("iubmb").equalsIgnoreCase("Y"));
 160  
                   }
 161  
           } finally {
 162  4
                   if (rs != null) rs.close();
 163  4
                   if (findStatement != null) findStatement.close();
 164  
           }
 165  4
           return result;
 166  
   }
 167  
 
 168  
   /**
 169  
    * Stores the given list of reactions into the database.
 170  
    *
 171  
    * @param reactions The vector of reactions.
 172  
    * @param enzymeId  The enzyme ID.
 173  
    * @param con       ...
 174  
    * @throws SQLException
 175  
    */
 176  
   public void insert(EnzymaticReactions reactions, Long enzymeId, Connection con)
 177  
   throws SQLException {
 178  1
     if (reactions == null) throw new NullPointerException("Parameter 'reactions' must not be null.");
 179  1
     if (enzymeId == null) throw new NullPointerException("Parameter 'enzymeId' must not be null.");
 180  1
     if (con == null) throw new NullPointerException("Parameter 'con' must not be null.");
 181  
 
 182  2
     for (int i = 0; i < reactions.size(); i++) {
 183  1
                 Reaction reaction = reactions.getReaction(i);
 184  1
                 EnzymeViewConstant view = reactions.getReactionView(i);
 185  1
                 boolean iubmb = reactions.getReactionIubmbFlag(i);
 186  1
             if (reaction.getId().equals(Reaction.NO_ID_ASSIGNED)){
 187  1
                     insertReaction(enzymeId, reaction, view, iubmb, i+1, con);
 188  
             } else {
 189  0
                     insertMapping(enzymeId, reaction.getId(), view, iubmb, i+1, con);
 190  
             }
 191  
     }
 192  1
   }
 193  
   
 194  
   /**
 195  
    * Inserts abstract reactions into the old REACTIONS table.
 196  
    * @param enzymeId
 197  
    * @param reaction
 198  
    * @param view
 199  
    * @param iubmb
 200  
    * @param orderIn
 201  
    * @param con
 202  
    * @throws SQLException
 203  
    */
 204  
   private void insertReaction(Long enzymeId, Reaction reaction,
 205  
                   EnzymeViewConstant view, boolean iubmb, int orderIn, Connection con)
 206  
   throws SQLException {
 207  1
           PreparedStatement stm = null;
 208  
           try {
 209  1
                   stm = con.prepareStatement(INSERT_ABSTRACT_STM);
 210  1
                   stm.setLong(1, enzymeId);
 211  1
                   stm.setString(2, reaction.getTextualRepresentation());
 212  1
                   stm.setInt(3, orderIn);
 213  1
                   stm.setString(4, reaction.getStatus().toString()); // NO status
 214  1
                   stm.setString(5, reaction.getSource().toString());
 215  1
                   stm.setString(6, view.toString());
 216  1
                   stm.execute();
 217  
           } finally {
 218  1
                   if (stm != null) stm.close();
 219  
           }
 220  1
   }
 221  
   
 222  
   /**
 223  
    * Inserts a mapping reaction-enzyme into the database.
 224  
    * @param enzymeId
 225  
    * @param reactionId
 226  
    * @param view
 227  
    * @param iubmb
 228  
    * @param orderIn
 229  
    * @param con
 230  
  * @throws SQLException
 231  
    */
 232  
   public void insertMapping(Long enzymeId, Long reactionId,
 233  
                   EnzymeViewConstant view, boolean iubmb,
 234  
                   int orderIn, Connection con) throws SQLException{
 235  0
           PreparedStatement stm = null;
 236  
           try {
 237  0
                   stm = con.prepareStatement(INSERT_STM);
 238  0
                   stm.setLong(1, reactionId);
 239  0
                   stm.setLong(2, enzymeId);
 240  0
                   stm.setString(3, view.toString());
 241  0
                   stm.setString(4, iubmb? "Y" : "N");
 242  0
                   stm.setInt(5, orderIn);
 243  0
                   stm.execute();
 244  0
                   LOGGER.info("[MAPPED] enzyme_id=" + enzymeId + " to reaction_id=" + reactionId);
 245  
           } finally {
 246  0
                   if (stm != null) stm.close();
 247  
           }
 248  0
   }
 249  
 
 250  
   /**
 251  
    * Replace the reactions in the database related to one enzyme
 252  
    * with those passed as parameter.
 253  
    *
 254  
    * @param enzymeId  The enzyme ID.
 255  
    * @param reactions The vector of reactions.
 256  
    * @param con
 257  
    * @throws SQLException
 258  
    */
 259  
   public void update(Long enzymeId, EnzymaticReactions reactions, Connection con)
 260  
   throws SQLException {
 261  0
     deleteAll(enzymeId, con);
 262  0
     insert(reactions, enzymeId, con);
 263  0
   }
 264  
 
 265  
   /**
 266  
    * Deletes all reactions mappings and abstract reactions related to one enzyme instance.
 267  
    *
 268  
    * @param enzymeId Enzyme ID of the enzyme instance.
 269  
    * @param con      ...
 270  
    * @throws SQLException
 271  
    */
 272  
   void deleteAll(Long enzymeId, Connection con) throws SQLException {
 273  2
     if (enzymeId == null) throw new NullPointerException("Parameter 'enzymeId' must not be null.");
 274  2
     if (con == null) throw new NullPointerException("Parameter 'con' must not be null.");
 275  
 
 276  2
     PreparedStatement stm = null;
 277  
     try {
 278  2
       stm = con.prepareStatement(DELETE_ALL_STM);
 279  2
       stm.setLong(1, enzymeId.longValue());
 280  2
       stm.execute();
 281  2
       stm.close();
 282  2
       stm = con.prepareStatement(DELETE_ALL_ABSTRACT_STM);
 283  2
       stm.setLong(1, enzymeId.longValue());
 284  2
       stm.execute();
 285  
     } finally {
 286  2
       if (stm != null) stm.close();
 287  
     }
 288  2
   }
 289  
 
 290  
   /**
 291  
    * Creates an empty Reaction object, with just an equation, source and status.
 292  
    * The reaction ID will be <code>null</code> for old plain text reactions, not
 293  
    * <code>null</code> in case of error while reading data from Rhea.
 294  
    * @param reactionId
 295  
    * @param equation
 296  
    * @param source A database code
 297  
    * @param status
 298  
    * @return
 299  
    * @throws java.sql.SQLException
 300  
    */
 301  
     private Reaction loadEmtpyReaction(Long reactionId, String equation,
 302  
             String source, String status)
 303  
     throws SQLException {
 304  3
         Reaction reaction = new Reaction(reactionId, equation, Database.fromCode(source));
 305  3
         reaction.setStatus(Status.valueOf(status));
 306  3
         return reaction;
 307  
     }
 308  
 
 309  
   /**
 310  
    * Creates the <code>Reaction</code> object from the given result set.
 311  
    *
 312  
    * @param rs The result set object.
 313  
    * @return a {@link Reaction}
 314  
    * @throws SQLException in case of a generic database problem.
 315  
    * @throws MapperException in case of problem retrieving the Rhea reaction.
 316  
    */
 317  
   private Reaction loadReaction(ResultSet rs) throws SQLException, MapperException {
 318  5
     assert rs != null : "Parameter 'rs' must not be null.";
 319  
 
 320  5
     String equation = rs.getString("equation");
 321  5
     String source = rs.getString("source");
 322  5
     Long reactionId = rs.getLong("reaction_id");
 323  5
     String status = rs.getString("status");
 324  
         // Convert enzyme status codes to Rhea-ction status codes:
 325  5
         if (status.equals("SU") || status.equals("PR")) status = "NO";
 326  
     Reaction reaction;
 327  5
     if (reactionId.equals(0L)){
 328  3
         reaction = loadEmtpyReaction(reactionId, equation, source, status);
 329  
     } else { // get the whole reaction
 330  
         try {
 331  2
             rheaReader.setConnection(rs.getStatement().getConnection());
 332  2
             reaction = rheaReader.findByReactionId(reactionId);
 333  0
         } catch (Exception ex) {
 334  0
             LOGGER.error("Unable to retrieve reaction from Rhea", ex);
 335  0
             reaction = loadEmtpyReaction(reactionId, equation, source, status);
 336  
         } finally {
 337  2
                 rheaReader.close();
 338  2
         }
 339  
     }
 340  5
     return reaction;
 341  
   }
 342  
 
 343  
         public void close() throws MapperException {
 344  11
                 rheaReader.close();
 345  11
         }
 346  
 
 347  
         @Override
 348  
         protected void finalize() throws Throwable {
 349  5
                 close();
 350  5
         }
 351  
 
 352  
 }