001// Copyright 2011 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.internal.jpa;
016
017import org.apache.tapestry5.ioc.internal.util.InternalUtils;
018import org.apache.tapestry5.jpa.EntityManagerManager;
019import org.apache.tapestry5.jpa.JpaConstants;
020
021import javax.persistence.EntityManager;
022import javax.persistence.EntityManagerFactory;
023import javax.persistence.PersistenceContext;
024import javax.persistence.metamodel.EntityType;
025import javax.persistence.metamodel.Metamodel;
026import java.util.Map;
027import java.util.Set;
028
029public class JpaInternalUtils
030{
031    public static PersistedEntity convertApplicationValueToPersisted(
032            final EntityManagerManager entityManagerManager, final Object newValue)
033    {
034        final EntityManager em = getEntityManagerFactory(entityManagerManager, newValue);
035
036        final EntityManagerFactory emf = em.getEntityManagerFactory();
037
038        final Map<String, Object> properties = emf.getProperties();
039
040        final String persistenceUnitName = (String) properties
041                .get(JpaConstants.PERSISTENCE_UNIT_NAME);
042
043        final Object id = emf.getPersistenceUnitUtil().getIdentifier(newValue);
044
045        return new PersistedEntity(newValue.getClass(), id, persistenceUnitName);
046    }
047
048    private static EntityManager getEntityManagerFactory(
049            final EntityManagerManager entityManagerManager, final Object entity)
050    {
051        final Map<String, EntityManager> entityManagers = entityManagerManager.getEntityManagers();
052
053        for (final EntityManager em : entityManagers.values())
054        {
055            final EntityManagerFactory emf = em.getEntityManagerFactory();
056
057            final Metamodel metamodel = emf.getMetamodel();
058
059            final Set<EntityType<?>> entities = metamodel.getEntities();
060
061            for (final EntityType<?> entityType : entities)
062            {
063                if (entityType.getJavaType() == entity.getClass())
064                {
065                    if (em.contains(entity))
066                    {
067                        return em;
068                    }
069                }
070            }
071        }
072
073        throw new IllegalArgumentException(
074                String.format(
075                        "Failed persisting the entity. The entity '%s' does not belong to any of the existing persistence contexts.",
076                        entity));
077    }
078
079    public static EntityManager getEntityManager(EntityManagerManager entityManagerManager,
080                                                 PersistenceContext annotation)
081    {
082        String unitName = annotation == null ? null : annotation.unitName();
083
084        if (InternalUtils.isNonBlank(unitName))
085            return entityManagerManager.getEntityManager(unitName);
086
087        Map<String, EntityManager> entityManagers = entityManagerManager.getEntityManagers();
088
089        if (entityManagers.size() == 1)
090            return entityManagers.values().iterator().next();
091
092        throw new RuntimeException("Unable to locate a single EntityManager. " +
093                "You must provide the persistence unit name as defined in the persistence.xml using the @PersistenceContext annotation.");
094    }
095}