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.data;
022
023import org.granite.logging.Logger;
024import org.granite.context.GraniteContext;
025import org.granite.messaging.amf.io.util.ClassGetter;
026import org.granite.tide.TidePersistenceManager;
027import org.granite.tide.TideTransactionManager;
028import org.granite.util.Reflections;
029
030
031/**
032 * Responsible for attaching a entity with the entity mangager
033 * @author cingram
034 *
035 */
036public abstract class AbstractTidePersistenceManager implements TidePersistenceManager {
037        
038        private static final Logger log = Logger.getLogger(AbstractTidePersistenceManager.class);
039        
040        protected TideTransactionManager tm;
041
042        
043        public AbstractTidePersistenceManager(TideTransactionManager tm) {
044                this.tm = tm;
045        if (this.tm == null)
046                throw new RuntimeException("transaction manager is null");
047        }
048        
049        
050        public Object attachEntity(Object entity, String[] propertyNames) {
051                return attachEntity(this, entity, propertyNames);
052        }
053        
054        /**
055         * Attach the passed in entity with the EntityManager.
056         * @param entity
057         * @return the attached entity object
058         */
059        public Object attachEntity(TidePersistenceManager pm, Object entity, String[] propertyNames) {
060                Object attachedEntity = null;
061        ClassGetter getter = GraniteContext.getCurrentInstance().getGraniteConfig().getClassGetter();
062        
063        try {
064                        Object tx = tm.begin(pm instanceof TideTransactionPersistenceManager ? (TideTransactionPersistenceManager)pm : null);
065                        if (tx == null)
066                            throw new RuntimeException("Could not initiate transaction for lazy initialization");
067                        
068                        try {
069                    //the get is called to give the children a chance to override and
070                    //use the implemented method
071                                if (propertyNames != null)
072                                        attachedEntity = fetchEntity(entity, propertyNames);
073                                else
074                                        attachedEntity = entity;
075                    
076                    if (attachedEntity != null && propertyNames != null) {
077                        for (int i = 0; i < propertyNames.length; i++) {
078                                Object initializedObj = attachedEntity;
079                                String[] pnames = propertyNames[i].split("\\.");
080                                for (int j = 0; j < pnames.length; j++)
081                                        initializedObj = Reflections.getGetterMethod(initializedObj.getClass(), pnames[j]).invoke(initializedObj);
082                                
083                            //This is here to make sure the list is forced to return a value while operating inside of a 
084                            //session. Forcing the  initialization of object.
085                            if (getter != null)
086                                getter.initialize(entity, propertyNames[i], initializedObj);
087                        }
088                    }
089                            
090                    tm.commit(tx);
091                    }
092                    catch (Exception e) {
093                        String propertyName = propertyNames != null && propertyNames.length > 0 ? propertyNames[0] : "";
094                        log.error(e, "Error during lazy-initialization of collection: %s", propertyName);
095                        tm.rollback(tx);
096                    }
097        }
098        finally {
099                close();
100        }
101        
102        return attachedEntity;
103        } 
104        
105        protected abstract void close();
106        
107    /**
108     * Fetch the entity with its lazy properties from the persistence context.
109     * @param entity entity to load
110     * @param fetch array of property names to fetch
111     * @return the entity with the persistence context.
112     */
113        public abstract Object fetchEntity(Object entity, String[] fetch);
114        
115}