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 */
022 package org.granite.tide.data;
023
024 import org.granite.logging.Logger;
025 import org.granite.context.GraniteContext;
026 import org.granite.messaging.amf.io.util.ClassGetter;
027 import org.granite.tide.TidePersistenceManager;
028 import org.granite.tide.TideTransactionManager;
029 import org.granite.util.Reflections;
030
031
032 /**
033 * Responsible for attaching a entity with the entity mangager
034 * @author cingram
035 *
036 */
037 public 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 }