/*
 * 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.    
 */
package org.apache.openjpa.persistence;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.persistence.*;
import javax.persistence.spi.LoadState;

import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.AutoDetach;
import org.apache.openjpa.kernel.Broker;
import org.apache.openjpa.kernel.BrokerFactory;
import org.apache.openjpa.kernel.DelegatingBrokerFactory;
import org.apache.openjpa.kernel.DelegatingFetchConfiguration;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.conf.Value;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Closeable;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.persistence.criteria.CriteriaBuilderImpl;
import org.apache.openjpa.persistence.criteria.OpenJPACriteriaBuilder;
import org.apache.openjpa.persistence.meta.MetamodelImpl;
import org.apache.openjpa.persistence.query.OpenJPAQueryBuilder;
import org.apache.openjpa.persistence.query.QueryBuilderImpl;

/**
 * Implementation of {@link EntityManagerFactory} that acts as a
 * facade to a {@link BrokerFactory}.
 *
 * @author Marc Prud'hommeaux
 */
@SuppressWarnings("serial")
public class EntityManagerFactoryImpl
    implements OpenJPAEntityManagerFactory, OpenJPAEntityManagerFactorySPI,
    Closeable, PersistenceUnitUtil {

    private static final Localizer _loc = Localizer.forPackage
        (EntityManagerFactoryImpl.class);

    private DelegatingBrokerFactory _factory = null;
    private transient Constructor<FetchPlan> _plan = null;
    private transient StoreCache _cache = null;
    private transient QueryResultCache _queryCache = null;
    private transient MetamodelImpl _metaModel;
    
    /**
     * Default constructor provided for auto-instantiation.
     */
    public EntityManagerFactoryImpl() {
    }

    /**
     * Supply delegate on construction.
     */
    public EntityManagerFactoryImpl(BrokerFactory factory) {
        setBrokerFactory(factory);
    }

    /**
     * Delegate.
     */
    public BrokerFactory getBrokerFactory() {
        return _factory.getDelegate();
    }

    /**
     * Delegate must be provided before use.
     */
    public void setBrokerFactory(BrokerFactory factory) {
        _factory = new DelegatingBrokerFactory(factory,
            PersistenceExceptions.TRANSLATOR);
    }

    public OpenJPAConfiguration getConfiguration() {
        return _factory.getConfiguration();
    }
    
    public Map<String,Object> getProperties() {
        Map<String,Object> props = _factory.getProperties();
        // convert to user readable values
        props.putAll(createEntityManager().getProperties());
        return props;
    }

    public Object putUserObject(Object key, Object val) {
        return _factory.putUserObject(key, val);
    }

    public Object getUserObject(Object key) {
        return _factory.getUserObject(key);
    }

    public StoreCache getStoreCache() {
        _factory.lock();
        try {
            if (_cache == null) {
                OpenJPAConfiguration conf = _factory.getConfiguration();
                _cache = new StoreCacheImpl(this,
                    conf.getDataCacheManagerInstance().getSystemDataCache());
            }
            return _cache;
        } finally {
            _factory.unlock();
        }
    }

    public StoreCache getStoreCache(String cacheName) {
        return new StoreCacheImpl(this, _factory.getConfiguration().
            getDataCacheManagerInstance().getDataCache(cacheName, true));
    }

    public QueryResultCache getQueryResultCache() {
        _factory.lock();
        try {
            if (_queryCache == null)
                _queryCache = new QueryResultCacheImpl(_factory.
                    getConfiguration().getDataCacheManagerInstance().
                    getSystemQueryCache());
            return _queryCache;
        } finally {
            _factory.unlock();
        }
    }

    public OpenJPAEntityManagerSPI createEntityManager() {
        return createEntityManager((Map) null);
    }

    @Override
    public OpenJPAEntityManagerSPI createEntityManager(SynchronizationType synchronizationType) {
        return createEntityManager(synchronizationType, null);
    }

    @Override
    public OpenJPAEntityManagerSPI createEntityManager(Map props) {
        return createEntityManager(SynchronizationType.SYNCHRONIZED, props);
    }


    /**
     * Creates and configures a entity manager with the given properties.
     *  
     * The property keys in the given map can be either qualified or not.
     * 
     * @return list of exceptions raised or empty list.
     */
    public OpenJPAEntityManagerSPI createEntityManager(SynchronizationType synchronizationType, Map props) {
        if (synchronizationType == null) {
            throw new NullPointerException("SynchronizationType must not be null");
        }
        if (SynchronizationType.UNSYNCHRONIZED.equals(synchronizationType)) {
            throw new UnsupportedOperationException("TODO - implement JPA 2.1 feature");
        }

        if (props == null) {
            props = Collections.EMPTY_MAP;
        }
        else if (!props.isEmpty()) {
            props = new HashMap(props);
        }


        OpenJPAConfiguration conf = getConfiguration();
        Log log = conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
        String user = (String) Configurations.removeProperty("ConnectionUserName", props);
        if (user == null)
            user = conf.getConnectionUserName();
        String pass = (String) Configurations.removeProperty("ConnectionPassword", props);
        if (pass == null)
            pass = conf.getConnectionPassword();

        String str = (String) Configurations.removeProperty("TransactionMode", props);
        boolean managed;
        if (str == null)
            managed = conf.isTransactionModeManaged();
        else {
            Value val = conf.getValue("TransactionMode");
            managed = Boolean.parseBoolean(val.unalias(str));
        }

        Object obj = Configurations.removeProperty("ConnectionRetainMode", props);
        int retainMode;
        if (obj instanceof Number) {
            retainMode = ((Number) obj).intValue();
        } else if (obj == null) {
            retainMode = conf.getConnectionRetainModeConstant();
        } else {
            Value val = conf.getValue("ConnectionRetainMode");
            try {
                retainMode = Integer.parseInt(val.unalias((String) obj));
            } catch (Exception e) {
                throw new ArgumentException(_loc.get("bad-em-prop", "openjpa.ConnectionRetainMode", obj),
                    new Throwable[]{ e }, obj, true);
            }
        }

        // javax.persistence.jtaDataSource and openjpa.ConnectionFactory name are equivalent.
        // prefer javax.persistence for now. 
        String cfName = (String) Configurations.removeProperty("jtaDataSource", props);  
        if(cfName == null) {
            cfName = (String) Configurations.removeProperty("ConnectionFactoryName", props);
        }
        
        String cf2Name = (String) Configurations.removeProperty("nonJtaDataSource", props); 
        
        if(cf2Name == null) { 
            cf2Name = (String) Configurations.removeProperty("ConnectionFactory2Name", props);
        }
        
        if (log != null && log.isTraceEnabled()) {
            if(StringUtil.isNotEmpty(cfName)) {
                log.trace("Found ConnectionFactoryName from props: " + cfName);
            }
            if(StringUtil.isNotEmpty(cf2Name)) {
                log.trace("Found ConnectionFactory2Name from props: " + cf2Name);
            }
        }
        validateCfNameProps(conf, cfName, cf2Name);

        Broker broker = _factory.newBroker(user, pass, managed, retainMode, false, cfName, cf2Name);
            
        // add autodetach for close and rollback conditions to the configuration
        broker.setAutoDetach(AutoDetach.DETACH_CLOSE, true);
        broker.setAutoDetach(AutoDetach.DETACH_ROLLBACK, true);
        broker.setDetachedNew(false);
        
        OpenJPAEntityManagerSPI em = newEntityManagerImpl(broker);

        // allow setting of other bean properties of EM
        Set<Map.Entry> entrySet = props.entrySet();
        for (Map.Entry entry : entrySet) {
            em.setProperty(entry.getKey().toString(), entry.getValue());
        }
        if (log != null && log.isTraceEnabled()) {
            log.trace(this + " created EntityManager " + em + ".");
        }
        return em;
    }

    /**
     * Create a new entity manager around the given broker.
     */
    protected EntityManagerImpl newEntityManagerImpl(Broker broker) {
        return new EntityManagerImpl(this, broker);
    }

    public void addLifecycleListener(Object listener, Class... classes) {
        _factory.addLifecycleListener(listener, classes);
    }

    public void removeLifecycleListener(Object listener) {
        _factory.removeLifecycleListener(listener);
    }

    public void addTransactionListener(Object listener) {
        _factory.addTransactionListener(listener);
    }

    public void removeTransactionListener(Object listener) {
        _factory.removeTransactionListener(listener);
    }

    public void close() {
        Log log = _factory.getConfiguration().getLog(OpenJPAConfiguration.LOG_RUNTIME);
        if (log.isTraceEnabled()) {
            log.trace(this + ".close() invoked.");
        }
        _factory.close();
    }

    public boolean isOpen() {
        return !_factory.isClosed();
    }

    public int hashCode() {
        return (_factory == null) ? 0 : _factory.hashCode();
    }

    public boolean equals(Object other) {
        if (other == this)
            return true;
        if ((other == null) || (other.getClass() != this.getClass()))
            return false;
        if (_factory == null)
            return false;
        return _factory.equals(((EntityManagerFactoryImpl) other)._factory);
    }

    /**
     * Create a store-specific facade for the given fetch configuration.
	 * If no facade class exists, we use the default {@link FetchPlan}.
     */
    FetchPlan toFetchPlan(Broker broker, FetchConfiguration fetch) {
        if (fetch == null)
            return null;

        if (fetch instanceof DelegatingFetchConfiguration)
            fetch = ((DelegatingFetchConfiguration) fetch).
                getInnermostDelegate();

        try {
            if (_plan == null) {
                Class storeType = (broker == null) ? null : broker.
                    getStoreManager().getInnermostDelegate().getClass();
                Class cls = _factory.getConfiguration().
                    getStoreFacadeTypeRegistry().
                    getImplementation(FetchPlan.class, storeType, 
                    		FetchPlanImpl.class);
                _plan = cls.getConstructor(FetchConfiguration.class);
            }
            return _plan.newInstance(fetch);
        } catch (InvocationTargetException ite) {
            throw PersistenceExceptions.toPersistenceException
                (ite.getTargetException());
        } catch (Exception e) {
            throw PersistenceExceptions.toPersistenceException(e);
        }
	}

    public Cache getCache() {
        _factory.assertOpen();
        return getStoreCache();
    }

    public OpenJPACriteriaBuilder getCriteriaBuilder() {
        return new CriteriaBuilderImpl().setMetaModel(getMetamodel());
    }
    
    public OpenJPAQueryBuilder getDynamicQueryBuilder() {
        return new QueryBuilderImpl(this);
    }

    public Set<String> getSupportedProperties() {
        return _factory.getSupportedProperties();
    }

    public MetamodelImpl getMetamodel() {
        if (_metaModel == null) {
            MetaDataRepository mdr = getConfiguration().getMetaDataRepositoryInstance();
            mdr.setValidate(MetaDataRepository.VALIDATE_RUNTIME, true);
            mdr.setResolve(MetaDataRepository.MODE_MAPPING_INIT, true);
            _metaModel = new MetamodelImpl(mdr);
        }
        return _metaModel;
    }

    public PersistenceUnitUtil getPersistenceUnitUtil() {
        return this;
    }

    @Override
    public void addNamedQuery(String name, Query query) {
        org.apache.openjpa.kernel.Query kernelQuery = ((QueryImpl<?>)query).getDelegate();
        MetaDataRepository metaDataRepositoryInstance = _factory.getConfiguration().getMetaDataRepositoryInstance();
        QueryMetaData metaData = metaDataRepositoryInstance.newQueryMetaData(null, null);
        metaData.setFrom(kernelQuery);
        metaDataRepositoryInstance.addQueryMetaData(metaData);
    }

    @Override
    public <T> T unwrap(Class<T> cls) {
        if (cls.isInstance(this)) {
            return cls.cast(this);
        }
        throw new javax.persistence.PersistenceException(this + " is not a " + cls);
    }

    @Override
    public <T> void addNamedEntityGraph(String graphName, EntityGraph<T> entityGraph) {
        throw new UnsupportedOperationException("JPA 2.1");
    }

    /**
     * Get the identifier for the specified entity.  If not managed by any
     * of the em's in this PU or not persistence capable, return null.
     */
    public Object getIdentifier(Object entity) {
        return OpenJPAPersistenceUtil.getIdentifier(this, entity);
    }

    public boolean isLoaded(Object entity) {
        return isLoaded(entity, null);
    }

    public boolean isLoaded(Object entity, String attribute) {
        if (entity == null) {
            return false;
        }
        return (OpenJPAPersistenceUtil.isManagedBy(this, entity) &&
                (OpenJPAPersistenceUtil.isLoaded(entity, attribute) == LoadState.LOADED));
    }
    
    private void validateCfNameProps(OpenJPAConfiguration conf, String cfName, String cf2Name) {
        if (StringUtil.isNotEmpty(cfName) || StringUtil.isNotEmpty(cf2Name)) {
            if (conf.getDataCache() != "false" && conf.getDataCache() != null) {
                throw new ArgumentException(_loc.get("invalid-cfname-prop", new Object[] {
                    "openjpa.DataCache (L2 Cache)",
                    cfName,
                    cf2Name }), null, null, true);

            }
            if (conf.getQueryCache() != "false" && conf.getQueryCache() != null) {
                throw new ArgumentException(_loc.get("invalid-cfname-prop", new Object[] {
                    "openjpa.QueryCache",
                    cfName,
                    cf2Name }), null, null, true);
            }
            Object syncMap = conf.toProperties(false).get("openjpa.jdbc.SynchronizeMappings");
            if(syncMap != null) { 
                throw new ArgumentException(_loc.get("invalid-cfname-prop", new Object[] {
                    "openjpa.jdbc.SynchronizeMappings",
                    cfName,
                    cf2Name }), null, null, true);
            }
        }
    }
}
