001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.tide.data;
022    
023    import java.io.Serializable;
024    import java.util.List;
025    
026    import javax.persistence.*;
027    
028    import org.granite.logging.Logger;
029    import org.granite.tide.TideTransactionManager;
030    
031    
032    /**
033     * Responsible for attaching a entity with the entity mangager
034     * @author cingram
035     *
036     */
037    public class JPAPersistenceManager extends AbstractTidePersistenceManager implements TideTransactionPersistenceManager {
038            
039            private static final Logger log = Logger.getLogger(JPAPersistenceManager.class);
040            
041            protected EntityManager entityManager;
042            protected EntityManagerFactory entityManagerFactory;
043            protected boolean shouldCloseEntityManager = false;
044    
045            
046            public JPAPersistenceManager(TideTransactionManager tm) {
047                    super(tm);
048            }
049    
050            public JPAPersistenceManager(EntityManager em) {
051                    this(em, null);
052            }
053            
054            public JPAPersistenceManager(EntityManager em, TideTransactionManager tm) {
055                    super(tm != null ? tm : new JPATransactionManager());
056                    
057            if (em == null)
058                    throw new RuntimeException("entity manager cannot be null");
059            
060            this.entityManager =  em;
061            }
062            
063            public JPAPersistenceManager(EntityManagerFactory emf) {
064                    this(emf, null);
065            }
066            
067            public JPAPersistenceManager(EntityManagerFactory emf, TideTransactionManager tm) {
068                    super(tm != null ? tm : new JPATransactionManager());
069                    
070            if (emf == null)
071                    throw new RuntimeException("entity manager factory cannot be null");
072            
073            this.entityManagerFactory = emf;
074            }
075            
076            public Object getCurrentTransaction() {
077                    initEntityManager();
078                EntityTransaction et = entityManager.getTransaction();   // Try to get a local resource transaction
079                et.begin();
080                return et;
081            }
082            
083            protected void initEntityManager() {
084                    if (this.entityManager != null)
085                            return;
086            this.entityManager = entityManagerFactory.createEntityManager();
087            shouldCloseEntityManager = true;
088            }
089            
090            @Override
091            public void close() {
092                    if (shouldCloseEntityManager && this.entityManager != null)
093                            this.entityManager.close();
094            }
095            
096            
097        /**
098         * Finds the entity with the JPA context.
099         * @return the entity with the JPA context.
100         */
101            @Override
102            public Object fetchEntity(Object entity, String[] fetch) {
103                    org.granite.util.Entity tideEntity = new org.granite.util.Entity(entity);
104                    Serializable id = (Serializable)tideEntity.getIdentifier();
105                    
106            if (id == null)
107                return null;
108            
109            initEntityManager();
110            
111            if (fetch == null || entityManager.getDelegate().getClass().getName().indexOf(".hibernate.") < 0)
112                    return entityManager.find(entity.getClass(), id);
113            
114            for (String f : fetch) {
115                    Query q = entityManager.createQuery("select e from " + entity.getClass().getName() + " e left join fetch e." + f + " where e = :entity");
116                    q.setParameter("entity", entity);
117                    List<?> results = q.getResultList();
118                    if (!results.isEmpty())
119                            entity = results.get(0);
120                    else
121                            log.warn("Could not find entity %s to initialize, id: %s", entity.getClass().getName(), id);  
122            }
123            return entity;
124            }
125    
126    }