package org.objectstyle.cayenne.jpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContextType;
import javax.persistence.spi.PersistenceUnitInfo;

/**
 * A base implementation of a non-JTA EntityManagerFactory.
 * 
 *..uthor Andrus Adamchik
 */
public class JpaEntityManagerFactory implements EntityManagerFactory {

    protected boolean open;
    protected PersistenceUnitInfo unitInfo;

    public JpaEntityManagerFactory(PersistenceUnitInfo unitInfo) {
        this.unitInfo = unitInfo;
        this.open = true;
    }

    /**
     * Indicates whether the factory is open. Returns true until the factory has been
     * closed.
     */
    public boolean isOpen() {
        return open;
    }

    /**
     * Close the factory, releasing any resources that it holds. After a factory instance
     * is closed, all methods invoked on it will throw an IllegalStateException, except
     * for isOpen, which will return false.
     */
    public void close() {
        checkClosed();
        this.open = false;
    }

    /**
     * Creates a new EntityManager of of type PersistenceContextType.TRANSACTION. This
     * method returns a new application-managed EntityManager instance (with a new
     * stand-alone persistence context) each time it is invoked. The ..ink #isOpen()}
     * method will return true on the returned instance.
     */
    public EntityManager createEntityManager() {
        return createEntityManager(PersistenceContextType.TRANSACTION);
    }

    /**
     * Create a new EntityManager of the specified persistence context type. This method
     * returns a new application-managed EntityManager instance (with a new stand-alone
     * persistence context) each time it is invoked. The ..ink #isOpen()} method will
     * return true on the returned instance.
     */
    public EntityManager createEntityManager(PersistenceContextType type) {
        checkClosed();

        // TODO: Andrus, 2/10/2006 - implement
        //throw new UnsupportedOperationException("TODO");
        
        JpaEntityManager manager = new JpaEntityManager(this, type);
        return manager;
    }

    /**
     * Getan EntityManager instance whose persistence context is propagated with the
     * current JTA transaction. If there is no persistence context bound to the current
     * JTA transaction, a new transaction-scoped persistence context is created and
     * associated with the transaction and the entity manager instance that is created and
     * returned. If no JTA transaction is in progress, an EntityManager instance is
     * created for which the persistence context will bepropagated with subsequent JTA
     * transactions.
     * 
     *..hrows IllegalStateException if called on an EntityManagerFactory that does not
     *             provide JTA EntityManagers.
     */
    public EntityManager getEntityManager() {
        checkClosed();
        throw new IllegalStateException(
                "JTA EntityManagers are not supported by this factory.");
    }

    /*
     * Throws an exception if called on closed factory.
     */
    void checkClosed() throws IllegalStateException {
        if (!isOpen()) {
            throw new IllegalStateException(
                    "An attempt to access closed EntityManagerFactory.");
        }
    }
}

