Coverage Report - org.apache.ojb.broker.accesslayer.PkEnumeration
 
Classes in this File Line Coverage Branch Coverage Complexity
PkEnumeration
N/A
N/A
4.333
 
 1  
 package org.apache.ojb.broker.accesslayer;
 2  
 
 3  
 /* Copyright 2002-2005 The Apache Software Foundation
 4  
  *
 5  
  * Licensed under the Apache License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 import java.lang.reflect.Constructor;
 19  
 import java.sql.SQLException;
 20  
 import java.util.Enumeration;
 21  
 import java.util.NoSuchElementException;
 22  
 
 23  
 import org.apache.ojb.broker.Identity;
 24  
 import org.apache.ojb.broker.PersistenceBroker;
 25  
 import org.apache.ojb.broker.PersistenceBrokerException;
 26  
 import org.apache.ojb.broker.PersistenceBrokerSQLException;
 27  
 import org.apache.ojb.broker.metadata.ClassDescriptor;
 28  
 import org.apache.ojb.broker.metadata.FieldDescriptor;
 29  
 import org.apache.ojb.broker.query.Query;
 30  
 import org.apache.ojb.broker.util.ConstructorHelper;
 31  
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 32  
 
 33  
 /**
 34  
  * this class can be used to create enumerations of PrimaryKey objects.
 35  
  * This is interesting for EJB finder methods
 36  
  * in BMP entity beans which must return such enumerations.
 37  
  * @author Thomas Mahler
 38  
  * @version $Id: PkEnumeration.java,v 1.1 2007-08-24 22:17:30 ewestfal Exp $
 39  
  */
 40  
 public class PkEnumeration implements Enumeration
 41  
 {
 42  
         static final long serialVersionUID = -834955711995869884L;
 43  
     protected boolean hasCalledCheck = false;
 44  
     protected boolean hasNext = false;
 45  
 
 46  
     protected PersistenceBroker broker;
 47  
 
 48  
     /**
 49  
      * The underlying jdbc resultset produced by select statement
 50  
      */
 51  
     protected ResultSetAndStatement resultSetAndStatment;
 52  
 
 53  
     /**
 54  
      * descriptor for the class of which items are to be found
 55  
      */
 56  
     protected ClassDescriptor classDescriptor;
 57  
 
 58  
     /**
 59  
      * the Constructor that is needed to build the PrimaryKey Objects
 60  
      */
 61  
     protected Constructor constructor;
 62  
 
 63  
     /**
 64  
      * PkEnumeration constructor.
 65  
      * @param query the SELECT statement gerating the underlying resultset
 66  
      * @param cld classDescriptor of the target entity class (say Article)
 67  
      * @param primaryKeyClass the entity classes PrimaryKey class (say ArticleKey).
 68  
      * this key-class MUST have a constructor with one argument of type org.apache.ojb.broker.Identity !
 69  
      */
 70  
     public PkEnumeration(Query query, ClassDescriptor cld, Class primaryKeyClass, PersistenceBroker broker)
 71  
     {
 72  
         this.resultSetAndStatment = broker.serviceJdbcAccess().executeQuery(query, cld);
 73  
         this.classDescriptor = cld;
 74  
         this.broker = broker;
 75  
         // get a contructor object that can be used to build instances of class primaryKeyClass
 76  
         try
 77  
         {
 78  
             Class[] argArray = {Identity.class};
 79  
             this.constructor = primaryKeyClass.getConstructor(argArray);
 80  
         }
 81  
         catch (NoSuchMethodException e)
 82  
         {
 83  
             LoggerFactory.getDefaultLogger().error(primaryKeyClass.getName()
 84  
                     + " must implement a Constructor with one argument of type org.apache.ojb.broker.Identity");
 85  
             throw new PersistenceBrokerException(e);
 86  
         }
 87  
         catch (SecurityException e)
 88  
         {
 89  
             LoggerFactory.getDefaultLogger().error(e);
 90  
             throw new PersistenceBrokerException(e);
 91  
         }
 92  
     }
 93  
 
 94  
     /**
 95  
      * returns an Identity object representing the current resultset row
 96  
      */
 97  
     private Identity getIdentityFromResultSet()
 98  
     {
 99  
 
 100  
         try
 101  
         {
 102  
             // 1. get an empty instance of the target class
 103  
             Constructor con = classDescriptor.getZeroArgumentConstructor();
 104  
             Object obj = ConstructorHelper.instantiate(con);
 105  
 
 106  
             // 2. fill only primary key values from Resultset
 107  
             Object colValue;
 108  
             FieldDescriptor fld;
 109  
             FieldDescriptor[] pkfields = classDescriptor.getPkFields();
 110  
             for (int i = 0; i < pkfields.length; i++)
 111  
             {
 112  
                 fld = pkfields[i];
 113  
                 colValue = fld.getJdbcType().getObjectFromColumn(resultSetAndStatment.m_rs, fld.getColumnName());
 114  
                 fld.getPersistentField().set(obj, colValue);
 115  
             }
 116  
             // 3. return the representing identity object
 117  
             return broker.serviceIdentity().buildIdentity(classDescriptor, obj);
 118  
         }
 119  
         catch (SQLException e)
 120  
         {
 121  
             throw new PersistenceBrokerSQLException("Error reading object from column", e);
 122  
         }
 123  
         catch (Exception e)
 124  
         {
 125  
             throw new PersistenceBrokerException("Error reading Identity from result set", e);
 126  
         }
 127  
     }
 128  
 
 129  
     /**
 130  
      * Tests if this enumeration contains more elements.
 131  
      * @return  <code>true</code> if and only if this enumeration object
 132  
      * contains at least one more element to provide;
 133  
      * <code>false</code> otherwise.
 134  
      */
 135  
     public boolean hasMoreElements()
 136  
     {
 137  
         try
 138  
         {
 139  
             if (!hasCalledCheck)
 140  
             {
 141  
                 hasCalledCheck = true;
 142  
                 hasNext = resultSetAndStatment.m_rs.next();
 143  
             }
 144  
         }
 145  
         catch (SQLException e)
 146  
         {
 147  
             LoggerFactory.getDefaultLogger().error(e);
 148  
             //releaseDbResources();
 149  
             hasNext = false;
 150  
         }
 151  
         finally
 152  
         {
 153  
             if(!hasNext)
 154  
             {
 155  
                 releaseDbResources();
 156  
             }
 157  
         }
 158  
         return hasNext;
 159  
     }
 160  
 
 161  
     private void releaseDbResources()
 162  
     {
 163  
         resultSetAndStatment.close();
 164  
         resultSetAndStatment = null;
 165  
     }
 166  
 
 167  
     /**
 168  
      * Returns the next element of this enumeration if this enumeration
 169  
      * object has at least one more element to provide.
 170  
      * @return     the next element of this enumeration.
 171  
      * @exception  NoSuchElementException  if no more elements exist.
 172  
      */
 173  
     public Object nextElement()
 174  
     {
 175  
         try
 176  
         {
 177  
             if (!hasCalledCheck)
 178  
             {    
 179  
                 hasMoreElements();
 180  
             }    
 181  
             hasCalledCheck = false;
 182  
             if (hasNext)
 183  
             {
 184  
                 Identity oid = getIdentityFromResultSet();
 185  
                 Identity[] args = {oid};
 186  
                 return this.constructor.newInstance(args);
 187  
             }
 188  
             else
 189  
                 throw new NoSuchElementException();
 190  
         }
 191  
         catch (Exception ex)
 192  
         {
 193  
             LoggerFactory.getDefaultLogger().error(ex);
 194  
             throw new NoSuchElementException();
 195  
         }
 196  
     }
 197  
 
 198  
         /**
 199  
          * protection just in case someone leaks.
 200  
          */
 201  
         protected void finalize()
 202  
         {
 203  
                 if(resultSetAndStatment != null)
 204  
         {
 205  
             LoggerFactory.getDefaultLogger().error("["+PkEnumeration.class.getName()+"] Found unclosed resources while finalize");
 206  
             releaseDbResources();
 207  
         }
 208  
         }
 209  
 }