Package com.impetus.kundera.persistence

Source Code of com.impetus.kundera.persistence.EntityManagerFactoryImpl$KunderaPersistenceUnitUtil

/*******************************************************************************
* * Copyright 2012 Impetus Infotech.
*  *
*  * 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.
******************************************************************************/
package com.impetus.kundera.persistence;


import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.persistence.Cache;
import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContextType;
import javax.persistence.PersistenceUnitUtil;
import javax.persistence.Query;
import javax.persistence.SynchronizationType;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.spi.LoadState;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.impetus.kundera.Constants;
import com.impetus.kundera.KunderaException;
import com.impetus.kundera.KunderaPersistence;
import com.impetus.kundera.PersistenceProperties;
import com.impetus.kundera.PersistenceUtilHelper;
import com.impetus.kundera.cache.CacheException;
import com.impetus.kundera.cache.CacheProvider;
import com.impetus.kundera.cache.NonOperationalCacheProvider;
import com.impetus.kundera.client.ClientResolverException;
import com.impetus.kundera.configure.ClientMetadataBuilder;
import com.impetus.kundera.configure.MetamodelConfiguration;
import com.impetus.kundera.configure.PersistenceUnitConfiguration;
import com.impetus.kundera.loader.ClientFactory;
import com.impetus.kundera.loader.ClientLifeCycleManager;
import com.impetus.kundera.loader.CoreLoader;
import com.impetus.kundera.metadata.KunderaMetadataManager;
import com.impetus.kundera.metadata.model.ApplicationMetadata;
import com.impetus.kundera.metadata.model.CoreMetadata;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.MetamodelImpl;
import com.impetus.kundera.metadata.model.PersistenceUnitMetadata;
import com.impetus.kundera.property.PropertyAccessorHelper;

/**
* Implementation class for {@link EntityManagerFactory}
*
* @author animesh.kumar
*/
public class EntityManagerFactoryImpl implements EntityManagerFactory
{

    /** the log used by this class. */
    private static Logger logger = LoggerFactory.getLogger(EntityManagerFactoryImpl.class);

    /** Whether or not the factory has been closed. */
    private boolean closed;

    /**
     * Persistence Unit Properties Overriden by user provided factory
     * properties.
     */
    private Map<String, Object> properties;

    // TODO: Move it to Application Metadata
    /** The cache provider. */
    private CacheProvider cacheProvider;

    /**
     * Array of persistence units. (Contains only one string usually except when
     * persisting in multiple data-stores)
     */
    private String[] persistenceUnits;

    // Transaction type
    private PersistenceUnitTransactionType transactionType;

    private final KunderaPersistenceUnitUtil util;

    private final PersistenceUtilHelper.MetadataCache cache = new PersistenceUtilHelper.MetadataCache();

    /** ClientFactory map holds one clientfactory for one persistence unit */
    private Map<String, ClientFactory> clientFactories = new ConcurrentHashMap<String, ClientFactory>();

    /** The Constant INSTANCE holds all application and core metadata. */
    private final KunderaMetadata kunderaMetadata = new KunderaMetadata();

    public EntityManagerFactoryImpl(PersistenceUnitInfo puInfo, Map<String, Object> properties)
    {
        // Load Core
        logger.info("Loading Core");
        new CoreLoader().load(kunderaMetadata);

        this.configurePersistenceUnit(puInfo, properties);
        this.util = new KunderaPersistenceUnitUtil(cache);
        this.configure(puInfo.getPersistenceUnitName(), properties);
    }

    /**
     * Use this if you want to construct this directly.
     *
     * @param persistenceUnit
     *            used to prefix the Cassandra domains
     * @param properties
     *            the properties
     */
    public EntityManagerFactoryImpl(String persistenceUnit, Map<String, Object> properties)
    {
        // Load Core
        logger.info("Loading Core");
        new CoreLoader().load(kunderaMetadata);

        this.configurePersistenceUnit(persistenceUnit, properties);
        this.util = new KunderaPersistenceUnitUtil(cache);
        this.configure(persistenceUnit, properties);
    }

    /**
     *
     * @param persistenceUnit
     * @param properties
     */
    private void configure(String persistenceUnit, Map<String, Object> properties)
    {
        Map<String, Object> propsMap = new HashMap<String, Object>();

        if (properties != null)
        {
            propsMap.putAll(properties);
        }

        // TODO Devise some better (JPA) way
        propsMap.put(Constants.PERSISTENCE_UNIT_NAME, persistenceUnit);
        this.properties = propsMap;
        this.persistenceUnits = persistenceUnit.split(Constants.PERSISTENCE_UNIT_SEPARATOR);

        // Configure metamodel.
        new MetamodelConfiguration(properties, kunderaMetadata, persistenceUnits).configure();

        // configure client factories
        configureClientFactories();

        // Initialize L2 cache
        // Invoke Client Loaders

        Set<PersistenceUnitTransactionType> txTypes = new HashSet<PersistenceUnitTransactionType>();

        for (String pu : persistenceUnits)
        {
            PersistenceUnitMetadata puMetadata = KunderaMetadataManager.getPersistenceUnitMetadata(kunderaMetadata,  pu);
            PersistenceUnitTransactionType txType = KunderaMetadataManager.getPersistenceUnitMetadata(kunderaMetadata, pu).getTransactionType();
            txTypes.add(txType);
            if (cacheProvider == null)
            {
                this.cacheProvider = initSecondLevelCache(puMetadata);
                this.cacheProvider.createCache(Constants.KUNDERA_SECONDARY_CACHE_NAME);
            }
        }

        if (txTypes.size() != 1)
        {
            throw new IllegalArgumentException(
                    "For polyglot persistence, it is mandatory for all persistence units to have same Transction type.");
        }
        else
        {
            this.transactionType = txTypes.iterator().next();
        }

        if (logger.isInfoEnabled())
        {
            logger.info("EntityManagerFactory created for persistence unit : " + persistenceUnit);
        }
    }

    /**
     * Close the factory, releasing any resources that it holds. After a factory
     * instance has been closed, all methods invoked on it will throw the
     * IllegalStateException, except for isOpen, which will return false. Once
     * an EntityManagerFactory has been closed, all its entity managers are
     * considered to be in the closed state.
     *
     * @throws IllegalStateException
     *             if the entity manager factory has been closed
     * @see javax.persistence.EntityManagerFactory#close()
     */
    @Override
    public final void close()
    {
        if (isOpen())
        {
            closed = true;

            // Shut cache provider down
            if (cacheProvider != null)
            {
                cacheProvider.shutdown();
            }

            for (String pu : persistenceUnits)
            {
                ((ClientLifeCycleManager) clientFactories.get(pu)).destroy();
            }
            this.persistenceUnits = null;
            this.properties = null;
            clientFactories.clear();
            clientFactories = new ConcurrentHashMap<String, ClientFactory>();
        }
        else
        {
            throw new IllegalStateException("Entity manager factory has been closed");
        }
    }

    /**
     * Create a new application-managed EntityManager. This method returns a new
     * EntityManager instance each time it is invoked. The isOpen method will
     * return true on the returned instance.
     *
     * @return entity manager instance
     * @throws IllegalStateException
     *             if the entity manager factory has been closed
     */
    @Override
    public final EntityManager createEntityManager()
    {
        // For Application managed persistence context, type is always EXTENDED
        if (isOpen())
        {
            return new EntityManagerImpl(this, transactionType, PersistenceContextType.EXTENDED);
        }
        throw new IllegalStateException("Entity manager factory has been closed.");
    }

    /**
     * Create a new application-managed EntityManager with the specified Map of
     * properties. This method returns a new EntityManager instance each time it
     * is invoked. The isOpen method will return true on the returned instance.
     *
     * @param map
     *            properties for entity manager
     * @return entity manager instance
     * @throws IllegalStateException
     *             if the entity manager factory has been closed
     */
    @Override
    public final EntityManager createEntityManager(Map map)
    {
        // For Application managed persistence context, type is always EXTENDED
        if (isOpen())
        {
            return new EntityManagerImpl(this, map, transactionType, PersistenceContextType.EXTENDED);
        }
        throw new IllegalStateException("Entity manager factory has been closed.");
    }

    /**
     * Indicates whether the factory is open. Returns true until the factory has
     * been closed.
     *
     * @return boolean indicating whether the factory is open
     * @see javax.persistence.EntityManagerFactory#isOpen()
     */
    @Override
    public final boolean isOpen()
    {
        return !closed;
    }

    /**
     * Return an instance of CriteriaBuilder for the creation of CriteriaQuery
     * objects.
     *
     * @return CriteriaBuilder instance
     * @throws IllegalStateException
     *             if the entity manager factory has been closed
     * @see javax.persistence.EntityManagerFactory#getCriteriaBuilder()
     */
    @Override
    public CriteriaBuilder getCriteriaBuilder()
    {
        if (isOpen())
        {
            return new KunderaCriteriaBuilder(this);
        }
        throw new IllegalStateException("Entity manager factory has been closed.");
    }

    /**
     * Return an instance of Metamodel interface for access to the metamodel of
     * the persistence unit.
     *
     * @return Metamodel instance
     * @throws IllegalStateException
     *             if the entity manager factory has been closed
     * @see javax.persistence.EntityManagerFactory#getMetamodel()
     */
    @Override
    public Metamodel getMetamodel()
    {
        if (isOpen())
        {
            MetamodelImpl metamodel = null;
            for (String pu : persistenceUnits)
            {
                metamodel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(pu);

                if (metamodel != null)
                {
                    return metamodel;
                }
            }
            // return
            // KunderaMetadataManager.getMetamodel(getPersistenceUnits());
        }
        throw new IllegalStateException("Entity manager factory has been closed.");
    }

    /**
     * Get the properties and associated values that are in effect for the
     * entity manager factory. Changing the contents of the map does not change
     * the configuration in effect.
     *
     * @return properties
     * @throws IllegalStateException
     *             if the entity manager factory has been closed
     * @see javax.persistence.EntityManagerFactory#getProperties()
     */
    @Override
    public Map<String, Object> getProperties()
    {
        if (isOpen())
        {
            return properties;
        }
        throw new IllegalStateException("Entity manager factory has been closed.");
    }

    /**
     * Access the cache that is associated with the entity manager factory (the
     * "second level cache").
     *
     * @return instance of the Cache interface
     * @throws IllegalStateException
     *             if the entity manager factory has been closed
     * @see javax.persistence.EntityManagerFactory#getCache()
     */
    @Override
    public Cache getCache()
    {
        if (isOpen())
        {
            return cacheProvider.getCache(Constants.KUNDERA_SECONDARY_CACHE_NAME);
        }
        throw new IllegalStateException("Entity manager factory has been closed.");
    }

    /**
     * Return interface providing access to utility methods for the persistence
     * unit.
     *
     * @return PersistenceUnitUtil interface
     * @throws IllegalStateException
     *             if the entity manager factory has been closed
     * @see javax.persistence.EntityManagerFactory#getPersistenceUnitUtil()
     */
    @Override
    public PersistenceUnitUtil getPersistenceUnitUtil()
    {
        if (!isOpen())
        {
            throw new IllegalStateException("Entity manager factory has been closed.");
        }
        return this.util;
    }

    /**
     * Initialize and load clientFactory for all persistenceUnit with external
     * properties.
     *
     * @param persistenceUnit
     * @param externalProperties
     */
    private void configureClientFactories()
    {
        ClientMetadataBuilder builder = new ClientMetadataBuilder(getProperties(), kunderaMetadata,
                getPersistenceUnits());
        builder.buildClientFactoryMetadata(clientFactories, kunderaMetadata);
    }

    /**
     * Inits the second level cache.
     *
     * @return the cache provider
     */
    private CacheProvider initSecondLevelCache(final PersistenceUnitMetadata puMetadata)
    {

        String classResourceName = (String) getProperties().get(PersistenceProperties.KUNDERA_CACHE_CONFIG_RESOURCE);

        classResourceName = classResourceName != null ? classResourceName : puMetadata
                .getProperty(PersistenceProperties.KUNDERA_CACHE_CONFIG_RESOURCE);

        String cacheProviderClassName = (String) getProperties()
                .get(PersistenceProperties.KUNDERA_CACHE_PROVIDER_CLASS);

        cacheProviderClassName = cacheProviderClassName != null ? cacheProviderClassName : puMetadata
                .getProperty(PersistenceProperties.KUNDERA_CACHE_PROVIDER_CLASS);

        CacheProvider cacheProvider = null;
        if (cacheProviderClassName != null)
        {
            try
            {
                Class<CacheProvider> cacheProviderClass = (Class<CacheProvider>) Class.forName(cacheProviderClassName);
                cacheProvider = cacheProviderClass.newInstance();
                cacheProvider.init(classResourceName);
            }
            catch (ClassNotFoundException e)
            {
                throw new CacheException("Could not find class " + cacheProviderClassName
                        + ". Check whether you spelled it correctly in persistence.xml", e);
            }
            catch (InstantiationException e)
            {
                throw new CacheException("Could not instantiate " + cacheProviderClassName, e);
            }
            catch (IllegalAccessException e)
            {
                throw new CacheException(e);
            }
        }
        if (cacheProvider == null)
        {
            cacheProvider = new NonOperationalCacheProvider();
        }
        return cacheProvider;
    }

    /**
     * Gets the persistence units.
     *
     * @return the persistence units
     */
    String[] getPersistenceUnits()
    {
        return persistenceUnits;
    }

    /**
     *
     * @param pu
     * @return
     */
    ClientFactory getClientFactory(final String pu)
    {
        ClientFactory clientFactory = clientFactories.get(pu);
        if (clientFactory != null)
        {
            return clientFactory;
        }
        logger.error("Client Factory Not Configured For Specified Client Type : ");
        throw new ClientResolverException("Client Factory Not Configured For Specified Client Type.");
    }

    /**
     *
     * @return Kundera metadata instance.
     */
    public KunderaMetadata getKunderaMetadataInstance()
    {
        return kunderaMetadata;
    }

    /**
     * The Class KunderaMetadata.
     *
     * @author amresh.singh
     */
    public static class KunderaMetadata
    {
        /* Metadata for Kundera core */
        /** The core metadata. */
        private CoreMetadata coreMetadata;

        /* User application specific metadata */
        /** The application metadata. */
        private ApplicationMetadata applicationMetadata;

        /**
         * Instantiates a new kundera metadata.
         */
        private KunderaMetadata()
        {

        }

        /**
         * Gets the application metadata.
         *
         * @return the applicationMetadata
         */
        public ApplicationMetadata getApplicationMetadata()
        {
            if (applicationMetadata == null)
            {
                applicationMetadata = new ApplicationMetadata();
            }
            return applicationMetadata;
        }

        /**
         * Gets the core metadata.
         *
         * @return the coreMetadata
         */
        public CoreMetadata getCoreMetadata()
        {
            return coreMetadata;
        }

        /**
         * Sets the application metadata.
         *
         * @param applicationMetadata
         *            the applicationMetadata to set
         */
        public void setApplicationMetadata(ApplicationMetadata applicationMetadata)
        {
            this.applicationMetadata = applicationMetadata;
        }

        /**
         * Sets the core metadata.
         *
         * @param coreMetadata
         *            the coreMetadata to set
         */
        public void setCoreMetadata(CoreMetadata coreMetadata)
        {
            this.coreMetadata = coreMetadata;
        }
    }

    /**
     * {@link PersistenceUnitUtil} for {@link KunderaPersistence}
     *
     * @author amresh.singh
     */
    private class KunderaPersistenceUnitUtil implements PersistenceUnitUtil
    {
        private transient PersistenceUtilHelper.MetadataCache cache;

        public KunderaPersistenceUnitUtil(PersistenceUtilHelper.MetadataCache cache)
        {
            this.cache = cache;
        }

        @Override
        public boolean isLoaded(Object entity, String attributeName)
        {
            LoadState state = PersistenceUtilHelper.isLoadedWithoutReference(entity, attributeName, this.cache);
            if (state == LoadState.LOADED)
            {
                return true;
            }
            if (state == LoadState.NOT_LOADED)
            {
                return false;
            }
            return (PersistenceUtilHelper.isLoadedWithReference(entity, attributeName, this.cache) != LoadState.NOT_LOADED);
        }

        @Override
        public boolean isLoaded(Object entity)
        {
            return (PersistenceUtilHelper.isLoaded(entity) != LoadState.NOT_LOADED);
        }

        @Override
        public Object getIdentifier(Object entity)
        {
            Class<?> entityClass = entity.getClass();
            EntityMetadata entityMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata,  entityClass);

            if (entityMetadata == null)
            {
                throw new IllegalArgumentException(entityClass + " is not an entity");
            }
            return PropertyAccessorHelper.getId(entity, entityMetadata);
        }

    }


    @Override
    public void addNamedQuery(String paramString, Query paramQuery)
    {
        //TODO: See https://github.com/impetus-opensource/Kundera/issues/457
        // Do nothing. Not yet implemented.
    }

    @Override
    public <T> T unwrap(Class<T> paramClass)
    {
        //TODO: See https://github.com/impetus-opensource/Kundera/issues/457
        // Do nothing. Not yet implemented.
        return null;
    }

    @Override
    public <T> void addNamedEntityGraph(String paramString, EntityGraph<T> paramEntityGraph)
    {
        //TODO: See https://github.com/impetus-opensource/Kundera/issues/457
        // Do nothing. Not yet implemented.
       
    }
   
    /**
     * One time initialization for persistence unit metadata.
     *
     * @param persistenceUnit
     *            Persistence Unit/ Comma separated persistence units
     */
    private void configurePersistenceUnit(String persistenceUnit, Map props)
    {
        // Invoke Persistence unit MetaData
        if (persistenceUnit == null)
        {
            throw new KunderaException("Persistence unit name should not be null");
        }
        if (logger.isInfoEnabled())
        {
            logger.info("Loading Persistence Unit MetaData For Persistence Unit(s) {}.", persistenceUnit);
        }

        String[] persistenceUnits = persistenceUnit.split(Constants.PERSISTENCE_UNIT_SEPARATOR);

        new PersistenceUnitConfiguration(props, kunderaMetadata, persistenceUnits).configure();
    }

    /**
     * One time initialization for persistence unit metadata.
     *
     * @param persistenceUnit
     *            Persistence Unit/ Comma separated persistence units
     */
    private void configurePersistenceUnit(PersistenceUnitInfo puInfo, Map props)
    {
        // Invoke Persistence unit MetaData
        if (puInfo.getPersistenceUnitName() == null)
        {
            throw new KunderaException("Persistence unit name should not be null");
        }
        if (logger.isInfoEnabled())
        {
            logger.info("Loading Persistence Unit MetaData For Persistence Unit(s) {}.",
                    puInfo.getPersistenceUnitName());
        }

        String[] persistenceUnits = puInfo.getPersistenceUnitName().split(Constants.PERSISTENCE_UNIT_SEPARATOR);

        new PersistenceUnitConfiguration(props, kunderaMetadata, persistenceUnits).configure(puInfo);
    }

    @Override
    public EntityManager createEntityManager(SynchronizationType paramSynchronizationType)
    {
        return createEntityManager();
    }

    @Override
    public EntityManager createEntityManager(SynchronizationType paramSynchronizationType, Map paramMap)
    {
        return createEntityManager(paramMap);
    }

}
TOP

Related Classes of com.impetus.kundera.persistence.EntityManagerFactoryImpl$KunderaPersistenceUnitUtil

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.