// $HeadURL$ // $Id$ // // Copyright © 2006, 2010, 2011, 2012 by the President and Fellows of Harvard College. // // Screensaver is an open-source project developed by the ICCB-L and NSRB labs // at Harvard Medical School. This software is distributed under the terms of // the GNU General Public License. package edu.harvard.med.screensaver.ui.arch.view; import java.io.Serializable; import org.apache.log4j.Logger; import org.springframework.transaction.annotation.Transactional; import edu.harvard.med.screensaver.db.GenericEntityDAO; import edu.harvard.med.screensaver.db.NoSuchEntityException; import edu.harvard.med.screensaver.model.Entity; import edu.harvard.med.screensaver.policy.EntityRestrictedException; import edu.harvard.med.screensaver.ui.arch.view.aspects.UICommand; public abstract class EntityViewerBackingBean<E extends Entity<?>> extends AbstractBackingBean implements EntityViewer<E> { protected static Logger log = Logger.getLogger(EntityViewerBackingBean.class); private EntityViewerBackingBean<E> _thisProxy; private GenericEntityDAO _dao; private Class<E> _entityClass; private E _entity; private String _viewerActionResult; protected EntityViewerBackingBean() {} protected EntityViewerBackingBean(EntityViewerBackingBean<E> thisProxy, Class<E> entityClass, String viewerActionResult, GenericEntityDAO dao) { _thisProxy = thisProxy; _entityClass = entityClass; _viewerActionResult = viewerActionResult; _dao = dao; } public EntityViewerBackingBean<E> getThisProxy() { if (_thisProxy == null) { log.warn("request for \"this proxy\" is returning non-proxied instance: " + this); return this; } return _thisProxy; } /** * Template method, called by {@link #setEntity(Entity)}. This method should * not be called directly by other code, use {@link #setEntity(Entity)}. This * method will be called within an active read-only transaction. The passed-in * entity may either be transient or managed by the current Hibernate session. The * entity argument will never be null. Implementations should only use the * passed-in entity argument, and should never call getEntity() (which would * return null). * * @param entity */ protected abstract void initializeViewer(E entity); /** * Subclasses should override this method to eager fetch relationships that * will be need when viewing the entity. It will be called within a transaction. */ protected abstract void initializeEntity(E entity); /*final*/ public E getEntity() { return _entity; } protected void _setEntity(E entity) { _entity = entity; } @Transactional /*final*/ public void setEntity(E entityIn) { E entity = null; if (entityIn == null || entityIn.isTransient()) { log.warn("tried to view a null or transient entity: " + entityIn); _entity = null; return; } entity = _dao.reloadEntity(entityIn, true); if (entity == null) { throw NoSuchEntityException.forEntityId(entityIn.getClass(), entityIn.getEntityId()); } // TODO: implement as aspect if (entity.isRestricted()) { throw new EntityRestrictedException(entity); } _entity = null; // prevent initializeViewer() implementations from erroneously calling getEntity() initializeEntity(entity); initializeViewer(entity); // note: we don't store the entity unless initializeViewer() returns successfully; otherwise, we might expose an entity that should be restricted _entity = (E) entity.restrict(); } public Class<E> getEntityClass() { return _entityClass; } @UICommand /*final*/ public String view() { return _viewerActionResult; } @UICommand @Transactional /*final*/ public String viewEntity(E entity) { setEntity(entity); return view(); } /** * View the entity identified in the 'entityId' request param */ @UICommand @Transactional /*final*/ public String viewEntity() { String entityIdAsString = (String) getRequestParameter("entityId"); Serializable entityId = convertEntityId(entityIdAsString); E entity = (E) _dao.findEntityById((Class<Entity>) (Class<?>) _entityClass, entityId); return _thisProxy.viewEntity(entity); } /** * Override this method if the entity type of this viewer has an ID that is not of type Integer */ protected Serializable convertEntityId(String entityIdAsString) { return Integer.valueOf(entityIdAsString); } /*final*/ public String reload() { return viewEntity(_entity); } protected GenericEntityDAO getDao() { return _dao; } }