/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

//
// This source code implements specifications defined by the Java
// Community Process. In order to remain compliant with the specification
// DO NOT add / change / or delete method signatures!
//
package javax.persistence;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.spi.LoadState;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceProviderResolver;
import javax.persistence.spi.PersistenceProviderResolverHolder;
import javax.persistence.spi.ProviderUtil;

/**
 * @version $Rev$ $Date$
 */

/**
 * Bootstrap class that is used to obtain {@link javax.persistence.EntityManagerFactory}
 * references.
 * 
 * Contains Geronimo implemented code as required by the JPA spec.
 */
public class Persistence {

    protected static final Set<PersistenceProvider> providers = new HashSet<PersistenceProvider>();
    // Changed to the hard coded PERSISTENCE_PROVIDER value to pass signature tests.
    // public static final java.lang.String PERSISTENCE_PROVIDER = PersistenceProvider.class.getName(); 
    public static final java.lang.String PERSISTENCE_PROVIDER = "javax.persistence.spi.PeristenceProvider";
    static final String PERSISTENCE_PROVIDER_PROPERTY = "javax.persistence.provider";
    static final String PERSISTENCE_PROVIDER_SERVICE = "META-INF/services/"
            + PersistenceProvider.class.getName();

    /**
     * Create and return an EntityManagerFactory for the named persistence unit.
     *
     * @param persistenceUnitName Name of the persistence unit
     * @return The factory for the specified persistence unit or null if none
     *         are applicable.
     */
    public static EntityManagerFactory createEntityManagerFactory(
            String persistenceUnitName) {
        return createEntityManagerFactory(persistenceUnitName, Collections.EMPTY_MAP);
    }

    /**
     * Create and return an EntityManagerFactory for the named persistence unit
     * using the given properties.
     *
     * @param persistenceUnitName Name of the persistence unit
     * @param properties Additional properties to use when creating the
     *                   persistence unit factory. These properties override any
     *                   values that have been configured elsewhere.
     * @return The factory for the specified persistence unit or null if none
     *         are applicable.
     */
    public static EntityManagerFactory createEntityManagerFactory(
            String persistenceUnitName, Map properties) {
        
        EntityManagerFactory factory = null;
        Map props = properties;
        if (props == null) {
            props = Collections.EMPTY_MAP;
        }
        
        // get the discovered set of providers
        PersistenceProviderResolver resolver =
            PersistenceProviderResolverHolder.getPersistenceProviderResolver();
        // following will throw PersistenceExceptions for invalid services
        List<PersistenceProvider> providers = resolver.getPersistenceProviders();

        /*
         * Geronimo/OpenJPA 1.0 unique behavior - Start by loading a provider
         * explicitly specified in the properties and return any exceptions.
         * The spec doesn't forbid providers that aren't a service - it only
         * states that they "should" be implemented as services in Sect. 9.2.
         * 
         * For 2.0 - We only perform the above behavior if the specified
         * provider is not in the discovered list.
         * 
         * Note: This special non-spec defined case will rethrow any encountered
         * Exceptions as a PersistenceException.
         */
        Object providerName = props.get(PERSISTENCE_PROVIDER_PROPERTY);
        if ((providerName != null) && (providerName instanceof String)) {
            boolean isLoaded = false;
            // search the discovered providers for this explicit provider
            for (PersistenceProvider provider : providers) {
                if (provider.getClass().getName().compareTo(providerName.toString()) == 0) {
                    isLoaded = true;
                    break;
                }
            }
            /*
             * Only try to explicitly create this provider if we didn't
             * find it as a service, while rethrowing any exceptions to
             * match the old 1.0 behavior
             */
            if (!isLoaded) {
                factory = createFactory(
                    providerName.toString(),
                    persistenceUnitName,
                    props);
                if (factory != null) {
                    return factory;
                }
            }
        }
        
        /*
         * Now, the default behavior of loading a provider from our resolver
         * Note:  Change in behavior from 1.0, which always returned exceptions:
         *   Spec states that a provider "must" return null if it
         *   cannot fulfill an EMF request, so ignore any exceptions
         *   that are thrown if we have more than one provider,
         *   so the other providers have a chance to return an EMF.
         *   Otherwise, return any exceptions and rethrow/wrapper as a
         *   PersistenceException if needed to match 1.0 behavior.
         */
        if (providers.size() == 1) {
            // allow any exceptions to pass thru to caller
            return providers.get(0).createEntityManagerFactory(
                persistenceUnitName, props);                    
        } else {
            for (PersistenceProvider provider : providers) {
                try {
                    factory = provider.createEntityManagerFactory(
                        persistenceUnitName, props);                    
                } catch (Exception e) {
                    // ignore and give other providers a chance
                }
                if (factory != null) {
                    return factory;
                }
            }
        }

        /*
         * Spec doesn't mention any exceptions thrown by this method if no emf
         * returned, but old 1.0 behavior always generated an EMF or exception.
         */
        throw new PersistenceException("No Persistence providers found for PU="
            + persistenceUnitName);
    }

    /*
     * Geronimo/OpenJPA private helper code for PERSISTENCE_PROVIDER_PROPERTY
     * @return EntityManagerFactory or null
     * @throws PersistenceException
     */
    private static EntityManagerFactory createFactory(String providerName,
            String persistenceUnitName, Map properties)
            throws PersistenceException {

        Class<?> providerClass;
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        if (cl == null)
            cl = Persistence.class.getClassLoader();
        try {
            providerClass = Class.forName(providerName, true, cl);
        } catch (Exception e) {
            throw new PersistenceException("Invalid or inaccessible explicit provider class: " +
                providerName, e);
        }
        try {
            PersistenceProvider provider = (PersistenceProvider) providerClass.newInstance();
            return provider.createEntityManagerFactory(persistenceUnitName, properties);
        } catch (Exception e) {
            throw new PersistenceException("Explicit error returned from provider: " +
                providerName, e);
        }
    }
    
    /*
    * @return PersistenceUtil instance
    * @since 2.0
    */
    public static PersistenceUtil getPersistenceUtil() {
        return new PersistenceUtilImpl();
    }
    
    /*
     * Geronimo implementation specific code
     */
    private static class PersistenceUtilImpl implements PersistenceUtil {

        /*
         * Determines the load state of the attribute of an entity 
         * @see javax.persistence.PersistenceUtil#isLoaded(java.lang.Object, java.lang.String)
         */
            public boolean isLoaded(Object entity, String attributeName) {
                boolean isLoaded = true;

                // Get the list of persistence providers from the resolver
                PersistenceProviderResolver ppr = 
                    PersistenceProviderResolverHolder.getPersistenceProviderResolver();
                List<PersistenceProvider> pps = ppr.getPersistenceProviders();

                // Iterate through the list using ProviderUtil.isLoadedWithoutReference()
                for (PersistenceProvider pp : pps) {
                    try {
                        ProviderUtil pu = pp.getProviderUtil();                        
                        LoadState ls = pu.isLoadedWithoutReference(entity, attributeName);
                        if (ls == LoadState.LOADED)
                            return true;
                        if (ls == LoadState.NOT_LOADED)
                            return false;
                    }
                    catch (Throwable t) {
                        // JPA 1.0 providers will not implement the getProviderUtil
                        // method.  Eat the exception and try the next provider.
                    }
                 }
                // Iterate through the list a second time using ProviderUtil.isLoadedWithReference()
                for (PersistenceProvider pp : pps) {
                    try {
                        ProviderUtil pu = pp.getProviderUtil();                        
                        LoadState ls = pu.isLoadedWithReference(entity, attributeName);
                        if (ls == LoadState.LOADED)
                            return true;
                        if (ls == LoadState.NOT_LOADED)
                            return false;
                    }
                    catch (Throwable t) {
                        // JPA 1.0 providers will not implement the getProviderUtil
                        // method.  Eat the exception and try the next provider.
                    }
                 }
                
                // All providers returned a load state of unknown.  Return true.
                return true;
            }

            public boolean isLoaded(Object entity) {
                // Get the list of persistence providers from the resolver
                PersistenceProviderResolver ppr = 
                    PersistenceProviderResolverHolder.getPersistenceProviderResolver();
                List<PersistenceProvider> pps = ppr.getPersistenceProviders();

                // Iterate through the list of providers, using ProviderUtil to
                // determine the load state
                for (PersistenceProvider pp : pps) {
                    try {
                        ProviderUtil pu = pp.getProviderUtil();
                        LoadState ls = pu.isLoaded(entity);
                        if (ls == LoadState.LOADED)
                            return true;
                        if (ls == LoadState.NOT_LOADED)
                            return false;
                        // Otherwise, load state is unknown.  Query the next provider.
                    }
                    catch (Throwable t) {
                        // JPA 1.0 providers will not implement the getProviderUtil
                        // method.  Eat the exception and try the next provider.
                    }                   
                }
                
                // All providers returned a load state of unknown.  Return true.
                return true;
            }
    }
    
}
