/* * ome.tools.hibernate.UpdateFilter * * Copyright 2006 University of Dundee. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.tools.hibernate; import java.util.Collection; import java.util.Date; import java.util.Map; import org.hibernate.Hibernate; import ome.model.IObject; import ome.model.internal.Permissions; import ome.util.ContextFilter; import ome.util.Filterable; /** * responsible for correlating entity identities during multiple calls to merge. * This occurs when {@link Collection collections} or arrays are passed into the * {@link ome.logic.UpdateImpl} save methods. * * @author Josh Moore, josh.moore at gmx.de * @see ome.api.IUpdate * @see ome.logic.UpdateImpl * @since 3.0-M3 */ public class UpdateFilter extends ContextFilter { /** * provides an external hook to unload all files which have already been * merged. * <p> * Merging produces a copy of an entity, so that all old entities should be * considered stale. By unloading them, one is forcing the API user to use * the {@link ome.model.internal.GraphHolder#getReplacement() replacement} * instead. * </p> * <p> * The replacement is set by {@link ome.security.basic.MergeEventListener} and this is the * signal that that entity can be unloaded. Usually, this method is invoked * by {@link ome.logic.UpdateImpl} * </p> * * @see ome.security.basic.MergeEventListener * @see ome.logic.UpdateImpl * @see IObject#unload() */ public void unloadReplacedObjects() { for (Object obj : _cache.keySet()) { if (hasReplacement(obj)) { ((IObject) obj).unload(); } } } /** * overrides {@link ContextFilter#filter(String, Object)} to allow only * certain types to enter the Hibernate system */ @Override public Object filter(String fieldId, Object o) { if (alreadySeen(o)) { return returnSeen(o); } Object result; if (o == null) { return null; } else if (o instanceof Enum) { result = o; // 5.1: Enums are unfiltered } else if (o instanceof ome.model.internal.Primitive) { result = o; // 5.1: units and named values as well } else if (o instanceof Filterable) { result = filter(fieldId, (Filterable) o); } else if (o instanceof Collection) { result = filter(fieldId, (Collection) o); } else if (o instanceof Map) { result = filter(fieldId, (Map) o); } else if (o instanceof Number || o instanceof String || o instanceof Date || o instanceof Boolean || o instanceof Permissions || o instanceof byte[] || o instanceof String[] || o instanceof String[][]) { result = o; } else { throw new RuntimeException( "Update Filter cannot allow unknown types to be saved." + o.getClass().getName() + " is not in {IObject,Collection,Map}"); } return result; } /** * overrides {@link ContextFilter#filter(String, Filterable)} to return * previously merged or previously checked items. */ @Override public Filterable filter(String fieldId, Filterable f) { if (alreadySeen(f)) { return (Filterable) returnSeen(f); } return super.filter(fieldId, f); } /** * overrides {@link ContextFilter#filter(String, Collection)} to return * previously checked {@link Collection collections}. */ @Override public Collection filter(String fieldId, Collection c) { if (alreadySeen(c)) { return (Collection) returnSeen(c); } return super.filter(fieldId, c); } /** * Prevents CountPerOwner from being loaded unnecessarily. * @see <a href="http://trac.openmicroscopy.org/ome/ticket/3978">Trac ticket #3978</a> */ @Override public Map filter(String fieldId, Map m) { if (fieldId != null && fieldId.endsWith("CountPerOwner")) { beforeFilter(fieldId, m); afterFilter(fieldId, m); return m; } return super.filter(fieldId, m); } // Helpers // ======================================================= protected boolean hasReplacement(Object o) { if (o instanceof IObject) { IObject obj = (IObject) o; if (obj.getGraphHolder().getReplacement() != null) { return true; } } return false; } protected boolean alreadySeen(Object o) { if (o == null) { return false; } if (!Hibernate.isInitialized(o)) { return true; } return hasReplacement(o) ? true : _cache.containsKey(o); } protected Object returnSeen(Object o) { if (o == null) { return null; } if (!Hibernate.isInitialized(o)) { return o; } if (hasReplacement(o)) { IObject obj = (IObject) o; IObject replacement = obj.getGraphHolder().getReplacement(); obj.unload(); return replacement; } return o; } }