/* This file is part of Cyclos (www.cyclos.org). A project of the Social Trade Organisation (www.socialtrade.org). Cyclos is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Cyclos 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 General Public License for more details. You should have received a copy of the GNU General Public License along with Cyclos; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package nl.strohalm.cyclos.dao; import nl.strohalm.cyclos.entities.Entity; import nl.strohalm.cyclos.entities.Relationship; import nl.strohalm.cyclos.entities.exceptions.DaoException; import nl.strohalm.cyclos.entities.exceptions.EntityNotFoundException; import nl.strohalm.cyclos.entities.exceptions.UnexpectedEntityException; import nl.strohalm.cyclos.utils.EntityHelper; import nl.strohalm.cyclos.utils.PropertyHelper; import nl.strohalm.cyclos.utils.binding.PropertyException; import nl.strohalm.cyclos.utils.hibernate.HibernateQueryHandler; import org.apache.commons.lang.ArrayUtils; import org.hibernate.Hibernate; import org.hibernate.ObjectNotFoundException; import org.hibernate.proxy.HibernateProxy; import org.springframework.orm.ObjectRetrievalFailureException; import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; /** * Implementation for fetch DAO * @author luis */ public class FetchDAOImpl extends HibernateDaoSupport implements FetchDAO { private HibernateQueryHandler hibernateQueryHandler; public void clearCache() { final HibernateTemplate ht = getHibernateTemplate(); ht.flush(); ht.clear(); } public <E extends Entity> E fetch(final E inputEntity, final Relationship... fetch) { return doFetch(inputEntity, fetch); } public boolean isInitialized(final Object value) { return !(value instanceof HibernateProxy) && Hibernate.isInitialized(value); } @SuppressWarnings("unchecked") public <E extends Entity> E reload(final E entity, final Relationship... fetch) throws UnexpectedEntityException, EntityNotFoundException, DaoException { if (entity == null || entity.getId() == null) { throw new UnexpectedEntityException(); } final HibernateTemplate ht = getHibernateTemplate(); final E current = (E) ht.load(EntityHelper.getRealClass(entity), entity.getId()); ht.refresh(current); return doFetch(current, fetch); } public void removeFromCache(final Entity entity) { getHibernateTemplate().evict(entity); } public void setHibernateQueryHandler(final HibernateQueryHandler hibernateQueryHandler) { this.hibernateQueryHandler = hibernateQueryHandler; } /** * Does the actual fetch from the database */ @SuppressWarnings("unchecked") private <E extends Entity> E doFetch(final E inputEntity, final Relationship... fetch) { if (inputEntity == null || inputEntity.getId() == null) { throw new UnexpectedEntityException(); } E entity; // Discover the entity real class and id final Class<? extends Entity> entityType = EntityHelper.getRealClass(inputEntity); final Long id = inputEntity.getId(); // Load and initialize the entity try { entity = (E) getHibernateTemplate().load(entityType, id); entity = (E) hibernateQueryHandler.initialize(entity); } catch (final ObjectRetrievalFailureException e) { throw new EntityNotFoundException(entityType, id); } catch (final ObjectNotFoundException e) { throw new EntityNotFoundException(entityType, id); } // ... and fetch each relationship if (!ArrayUtils.isEmpty(fetch)) { for (final Relationship relationship : fetch) { if (relationship == null) { continue; } try { final String name = relationship.getName(); Object bean = entity; String first = PropertyHelper.firstProperty(name); String nested = PropertyHelper.nestedPath(name); while (bean != null && first != null) { final Object value = hibernateQueryHandler.initializeProperty(bean, first); bean = value; first = PropertyHelper.firstProperty(nested); nested = PropertyHelper.nestedPath(nested); } } catch (final PropertyException e) { // Ok - nonexisting property. Probably fetching a relationship that only exists in one of the subclasses, and trying to use it no // another one } catch (final Exception e) { throw new PropertyException(entity, relationship.getName(), e); } } } return entity; } }