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 org.granite.logging.Logger;
024 import org.granite.context.GraniteContext;
025 import org.granite.messaging.amf.io.util.ClassGetter;
026 import org.granite.tide.TidePersistenceManager;
027 import org.granite.tide.TideTransactionManager;
028 import org.granite.util.Reflections;
029
030
031 /**
032 * Responsible for attaching a entity with the entity mangager
033 * @author cingram
034 *
035 */
036 public 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 Object tx = tm.begin(pm instanceof TideTransactionPersistenceManager ? (TideTransactionPersistenceManager)pm : null);
064 if (tx == null)
065 throw new RuntimeException("Could not initiate transaction for lazy initialization");
066
067 try {
068 //the get is called to give the children a chance to override and
069 //use the implemented method
070 if (propertyNames != null)
071 attachedEntity = fetchEntity(entity, propertyNames);
072 else
073 attachedEntity = entity;
074
075 if (attachedEntity != null && propertyNames != null) {
076 for (int i = 0; i < propertyNames.length; i++) {
077 Object initializedObj = attachedEntity;
078 String[] pnames = propertyNames[i].split("\\.");
079 for (int j = 0; j < pnames.length; j++)
080 initializedObj = Reflections.getGetterMethod(initializedObj.getClass(), pnames[j]).invoke(initializedObj);
081
082 //This is here to make sure the list is forced to return a value while operating inside of a
083 //session. Forcing the initialization of object.
084 if (getter != null)
085 getter.initialize(entity, propertyNames[i], initializedObj);
086 }
087 }
088
089 tm.commit(tx);
090 }
091 catch (Exception e) {
092 String propertyName = propertyNames != null && propertyNames.length > 0 ? propertyNames[0] : "";
093 log.error(e, "Error during lazy-initialization of collection: %s", propertyName);
094 tm.rollback(tx);
095 }
096
097 return attachedEntity;
098 }
099
100 /**
101 * Fetch the entity with its lazy properties from the persistence context.
102 * @param entity entity to load
103 * @param fetch array of property names to fetch
104 * @return the entity with the persistence context.
105 */
106 public abstract Object fetchEntity(Object entity, String[] fetch);
107
108 }