Package org.apache.ojb.broker.accesslayer

Source Code of org.apache.ojb.broker.accesslayer.PkEnumeration

package org.apache.ojb.broker.accesslayer;

/* Copyright 2002-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.lang.reflect.Constructor;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.NoSuchElementException;

import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.PersistenceBrokerSQLException;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.util.ConstructorHelper;
import org.apache.ojb.broker.util.logging.LoggerFactory;

/**
* this class can be used to create enumerations of PrimaryKey objects.
* This is interesting for EJB finder methods
* in BMP entity beans which must return such enumerations.
* @author Thomas Mahler
* @version $Id: PkEnumeration.java,v 1.17.2.3 2005/12/21 22:22:59 tomdz Exp $
*/
public class PkEnumeration implements Enumeration
{
  static final long serialVersionUID = -834955711995869884L;
    protected boolean hasCalledCheck = false;
    protected boolean hasNext = false;

    protected PersistenceBroker broker;

    /**
     * The underlying jdbc resultset produced by select statement
     */
    protected ResultSetAndStatement resultSetAndStatment;

    /**
     * descriptor for the class of which items are to be found
     */
    protected ClassDescriptor classDescriptor;

    /**
     * the Constructor that is needed to build the PrimaryKey Objects
     */
    protected Constructor constructor;

    /**
     * PkEnumeration constructor.
     * @param query the SELECT statement gerating the underlying resultset
     * @param cld classDescriptor of the target entity class (say Article)
     * @param primaryKeyClass the entity classes PrimaryKey class (say ArticleKey).
     * this key-class MUST have a constructor with one argument of type org.apache.ojb.broker.Identity !
     */
    public PkEnumeration(Query query, ClassDescriptor cld, Class primaryKeyClass, PersistenceBroker broker)
    {
        this.resultSetAndStatment = broker.serviceJdbcAccess().executeQuery(query, cld);
        this.classDescriptor = cld;
        this.broker = broker;
        // get a contructor object that can be used to build instances of class primaryKeyClass
        try
        {
            Class[] argArray = {Identity.class};
            this.constructor = primaryKeyClass.getConstructor(argArray);
        }
        catch (NoSuchMethodException e)
        {
            LoggerFactory.getDefaultLogger().error(primaryKeyClass.getName()
                    + " must implement a Constructor with one argument of type org.apache.ojb.broker.Identity");
            throw new PersistenceBrokerException(e);
        }
        catch (SecurityException e)
        {
            LoggerFactory.getDefaultLogger().error(e);
            throw new PersistenceBrokerException(e);
        }
    }

    /**
     * returns an Identity object representing the current resultset row
     */
    private Identity getIdentityFromResultSet()
    {

        try
        {
            // 1. get an empty instance of the target class
            Constructor con = classDescriptor.getZeroArgumentConstructor();
            Object obj = ConstructorHelper.instantiate(con);

            // 2. fill only primary key values from Resultset
            Object colValue;
            FieldDescriptor fld;
            FieldDescriptor[] pkfields = classDescriptor.getPkFields();
            for (int i = 0; i < pkfields.length; i++)
            {
                fld = pkfields[i];
                colValue = fld.getJdbcType().getObjectFromColumn(resultSetAndStatment.m_rs, fld.getColumnName());
                fld.getPersistentField().set(obj, colValue);
            }
            // 3. return the representing identity object
            return broker.serviceIdentity().buildIdentity(classDescriptor, obj);
        }
        catch (SQLException e)
        {
            throw new PersistenceBrokerSQLException("Error reading object from column", e);
        }
        catch (Exception e)
        {
            throw new PersistenceBrokerException("Error reading Identity from result set", e);
        }
    }

    /**
     * Tests if this enumeration contains more elements.
     * @return  <code>true</code> if and only if this enumeration object
     * contains at least one more element to provide;
     * <code>false</code> otherwise.
     */
    public boolean hasMoreElements()
    {
        try
        {
            if (!hasCalledCheck)
            {
                hasCalledCheck = true;
                hasNext = resultSetAndStatment.m_rs.next();
            }
        }
        catch (SQLException e)
        {
            LoggerFactory.getDefaultLogger().error(e);
            //releaseDbResources();
            hasNext = false;
        }
        finally
        {
            if(!hasNext)
            {
                releaseDbResources();
            }
        }
        return hasNext;
    }

    private void releaseDbResources()
    {
        resultSetAndStatment.close();
        resultSetAndStatment = null;
    }

    /**
     * Returns the next element of this enumeration if this enumeration
     * object has at least one more element to provide.
     * @return     the next element of this enumeration.
     * @exception  NoSuchElementException  if no more elements exist.
     */
    public Object nextElement()
    {
        try
        {
            if (!hasCalledCheck)
            {   
                hasMoreElements();
            }   
            hasCalledCheck = false;
            if (hasNext)
            {
                Identity oid = getIdentityFromResultSet();
                Identity[] args = {oid};
                return this.constructor.newInstance(args);
            }
            else
                throw new NoSuchElementException();
        }
        catch (Exception ex)
        {
            LoggerFactory.getDefaultLogger().error(ex);
            throw new NoSuchElementException();
        }
    }

  /**
   * protection just in case someone leaks.
   */
  protected void finalize()
  {
    if(resultSetAndStatment != null)
        {
            LoggerFactory.getDefaultLogger().error("["+PkEnumeration.class.getName()+"] Found unclosed resources while finalize");
            releaseDbResources();
        }
  }
}
TOP

Related Classes of org.apache.ojb.broker.accesslayer.PkEnumeration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.