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
021package org.granite.tide.seam.lazy;
022
023import java.io.Serializable;
024
025import javax.persistence.EntityManager;
026import javax.persistence.Query;
027
028import org.granite.context.GraniteContext;
029import org.granite.messaging.amf.io.util.ClassGetter;
030import org.granite.tide.TidePersistenceManager;
031import org.jboss.seam.Entity;
032import org.jboss.seam.util.Reflections;
033
034/**
035 * Manager responsible for the maintaining a refernce for the PersistenceContext(JPA). 
036 * @author CIngram
037 */
038public class PersistenceContextManager implements TidePersistenceManager  {
039        
040        private EntityManager em;
041        
042        public PersistenceContextManager() {
043        }
044        
045        public PersistenceContextManager(EntityManager em) {
046                this.em = em;
047        }
048        
049        /**
050         * Attach the passed in entity with the EntityManager.
051         * @param entity
052         * @return the attached entity object
053         */
054        public Object attachEntity(Object entity, String[] propertyNames) {
055                Object attachedEntity = null;
056        ClassGetter getter = GraniteContext.getCurrentInstance().getGraniteConfig().getClassGetter();
057                
058                //the get is called to give the children a chance to override and
059                //use the implemented method
060                attachedEntity = fetchEntity(entity, propertyNames);
061
062            if (attachedEntity != null && propertyNames != null) {
063                for (int i = 0; i < propertyNames.length; i++) {
064                        try {
065                                Object initializedObj = Reflections.getGetterMethod(attachedEntity.getClass(), propertyNames[i]).invoke(attachedEntity);
066                            
067                                //This is here to make sure the list is forced to return a value while operating inside of a 
068                                //session. Forcing the  initialization of object.
069                        if (getter != null)
070                            getter.initialize(entity, propertyNames[i], initializedObj);
071                        }
072                        catch (Exception e) {
073                                throw new RuntimeException("Could not initialize entity " + attachedEntity, e);
074                        }
075                }
076        }
077                
078                return attachedEntity;
079        } 
080        
081        /**
082         * attaches the entity to the JPA context.
083         * @return the attached entity
084         */
085        public Object fetchEntity(Object entity, String[] fetch) {
086        Serializable id = (Serializable)Entity.forClass(entity.getClass()).getIdentifier(entity);
087        if (id == null)
088            return null;
089        
090        if (fetch == null || em.getDelegate().getClass().getName().indexOf(".hibernate.") < 0)
091                return em.find(entity.getClass(), id);
092        
093        for (String f : fetch) {
094                Query q = em.createQuery("select e from " + entity.getClass().getName() + " e left join fetch e." + f + " where e = :entity");
095                q.setParameter("entity", entity);
096                entity = q.getSingleResult();
097        }
098        return entity;
099        }
100}