001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *   Granite Data Services is free software; you can redistribute it and/or
008 *   modify it under the terms of the GNU Lesser General Public
009 *   License as published by the Free Software Foundation; either
010 *   version 2.1 of the License, or (at your option) any later version.
011 *
012 *   Granite Data Services is distributed in the hope that it will be useful,
013 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
014 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 *   General Public License for more details.
016 *
017 *   You should have received a copy of the GNU Lesser General Public
018 *   License along with this library; if not, write to the Free Software
019 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 *   USA, or see <http://www.gnu.org/licenses/>.
021 */
022package org.granite.tide.data;
023
024import org.granite.logging.Logger;
025import org.granite.context.GraniteContext;
026import org.granite.messaging.amf.io.util.ClassGetter;
027import org.granite.tide.TidePersistenceManager;
028import org.granite.tide.TideTransactionManager;
029import org.granite.util.Reflections;
030
031
032/**
033 * Responsible for attaching a entity with the entity mangager
034 * @author cingram
035 *
036 */
037public abstract class AbstractTidePersistenceManager implements TidePersistenceManager {
038        
039        private static final Logger log = Logger.getLogger(AbstractTidePersistenceManager.class);
040        
041        protected TideTransactionManager tm;
042
043        
044        public AbstractTidePersistenceManager(TideTransactionManager tm) {
045                this.tm = tm;
046        if (this.tm == null)
047                throw new RuntimeException("transaction manager is null");
048        }
049        
050        
051        public Object attachEntity(Object entity, String[] propertyNames) {
052                return attachEntity(this, entity, propertyNames);
053        }
054        
055        /**
056         * Attach the passed in entity with the EntityManager.
057         * @param entity
058         * @return the attached entity object
059         */
060        public Object attachEntity(TidePersistenceManager pm, Object entity, String[] propertyNames) {
061                Object attachedEntity = null;
062        ClassGetter getter = GraniteContext.getCurrentInstance().getGraniteConfig().getClassGetter();
063        
064        try {
065                        Object tx = tm.begin(pm instanceof TideTransactionPersistenceManager ? (TideTransactionPersistenceManager)pm : null);
066                        if (tx == null)
067                            throw new RuntimeException("Could not initiate transaction for lazy initialization");
068                        
069                        try {
070                    //the get is called to give the children a chance to override and
071                    //use the implemented method
072                                if (propertyNames != null)
073                                        attachedEntity = fetchEntity(entity, propertyNames);
074                                else
075                                        attachedEntity = entity;
076                    
077                    if (attachedEntity != null && propertyNames != null) {
078                        for (int i = 0; i < propertyNames.length; i++) {
079                                Object initializedObj = attachedEntity;
080                                String[] pnames = propertyNames[i].split("\\.");
081                                for (int j = 0; j < pnames.length; j++)
082                                        initializedObj = Reflections.getGetterMethod(initializedObj.getClass(), pnames[j]).invoke(initializedObj);
083                                
084                            //This is here to make sure the list is forced to return a value while operating inside of a 
085                            //session. Forcing the  initialization of object.
086                            if (getter != null)
087                                getter.initialize(entity, propertyNames[i], initializedObj);
088                        }
089                    }
090                            
091                    tm.commit(tx);
092                    }
093                    catch (Exception e) {
094                        String propertyName = propertyNames != null && propertyNames.length > 0 ? propertyNames[0] : "";
095                        log.error(e, "Error during lazy-initialization of collection: %s", propertyName);
096                        tm.rollback(tx);
097                    }
098        }
099        finally {
100                close();
101        }
102        
103        return attachedEntity;
104        } 
105        
106        protected abstract void close();
107        
108    /**
109     * Fetch the entity with its lazy properties from the persistence context.
110     * @param entity entity to load
111     * @param fetch array of property names to fetch
112     * @return the entity with the persistence context.
113     */
114        public abstract Object fetchEntity(Object entity, String[] fetch);
115        
116}