/** * GRANITE DATA SERVICES * Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S. * * This file is part of the Granite Data Services Platform. * * Granite Data Services is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * Granite Data Services is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA, or see <http://www.gnu.org/licenses/>. */ package org.granite.tide.seam.lazy; import static org.jboss.seam.annotations.Install.FRAMEWORK; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import javax.persistence.EntityManager; import org.granite.tide.TidePersistenceManager; import org.granite.tide.data.DataMergeContext; import org.jboss.seam.Component; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Install; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.intercept.BypassInterceptors; import org.jboss.seam.core.Expressions; import org.jboss.seam.log.Log; /** * Initializes a request for a passed in entity and a lazy property. * @author CIngram,VDanda */ @Name("org.granite.tide.seam.seamInitializer") @Scope(ScopeType.CONVERSATION) @Install(precedence=FRAMEWORK) @BypassInterceptors public class SeamInitializer implements Serializable { private static final long serialVersionUID = 1L; @Logger Log log; private transient TidePersistenceManager pm = null; private Set<Object> loadedEntities = new HashSet<Object>(); /** * Initiliazes the property for the passed in entity. It is attached to an associated context * and then the property is accessed. * @return Returns result from initializing the property. */ @Transactional public Object lazyInitialize(Object entity, String[] propertyNames) { boolean removeAfterCall = false; restoreLoadedEntities(); try { if (entity instanceof String) { String expression = "${" + entity + "}"; Expressions.ValueExpression<Object> valueExpr = Expressions.instance().createValueExpression(expression, Object.class); entity = valueExpr.getValue(); } if (pm == null) { removeAfterCall = true; pm = tryToDetermineInitiailzer(); if (pm == null) throw new RuntimeException("TideInitializer is null, Entities with Lazy relationships have to be retrieved in a conversation, or the EntityManager name must be entityManager"); } Object initializedEntity = pm.attachEntity(entity, propertyNames); saveLoadedEntities(); return initializedEntity; } finally { if (removeAfterCall) Component.forName("org.granite.tide.seam.seamInitializer").destroy(this); } } /** * Try to determine what type of persistence the application is using. * If the EntityManager is stored under entityManager or if the Hibernate session is * stored under session. Then the context will be found and used. This is only called if a * ITidePersistenceManager is not found, probably because the query was not run in a conversation. * @return The appropriate manager for the persistence context being used, if it can be determined * otherwise a null is returned. */ protected TidePersistenceManager tryToDetermineInitiailzer() { EntityManager em = findEntityManager(); if (em != null) return TidePersistenceFactory.createTidePersistence(null, em); return null; } /** * Try to find the entityManager if possible. Assume that the entityManager is stored under * entityManager. * @return The Current Entity manager */ protected EntityManager findEntityManager() { return (EntityManager) Component.getInstance("entityManager"); } /** * @return A instance of this component for the conversation. */ public static SeamInitializer instance() { return (SeamInitializer)Component.getInstance(SeamInitializer.class); } public void setTidePersistenceManager(TidePersistenceManager pm) { this.pm = pm; } public TidePersistenceManager getTidePersistenceManager() { return this.pm; } public void restoreLoadedEntities() { DataMergeContext.restoreLoadedEntities(loadedEntities); } public void saveLoadedEntities() { for (Object entity : DataMergeContext.getLoadedEntities()) loadedEntities.add(entity); } }