src/core/net/sf/basedb/util/overview/node/NodeFactory.java

Code
Comments
Other
Rev Date Author Line
4740 05 Feb 09 nicklas 1 /**
4740 05 Feb 09 nicklas 2   $Id$
4740 05 Feb 09 nicklas 3
4740 05 Feb 09 nicklas 4   Copyright (C) 2008 Nicklas Nordborg
4740 05 Feb 09 nicklas 5
4740 05 Feb 09 nicklas 6   This file is part of BASE - BioArray Software Environment.
4740 05 Feb 09 nicklas 7   Available at http://base.thep.lu.se/
4740 05 Feb 09 nicklas 8
4740 05 Feb 09 nicklas 9   BASE is free software; you can redistribute it and/or
4740 05 Feb 09 nicklas 10   modify it under the terms of the GNU General Public License
4740 05 Feb 09 nicklas 11   as published by the Free Software Foundation; either version 3
4740 05 Feb 09 nicklas 12   of the License, or (at your option) any later version.
4740 05 Feb 09 nicklas 13
4740 05 Feb 09 nicklas 14   BASE is distributed in the hope that it will be useful,
4740 05 Feb 09 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
4740 05 Feb 09 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4740 05 Feb 09 nicklas 17   GNU General Public License for more details.
4740 05 Feb 09 nicklas 18
4740 05 Feb 09 nicklas 19   You should have received a copy of the GNU General Public License
4740 05 Feb 09 nicklas 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
4740 05 Feb 09 nicklas 21 */
4740 05 Feb 09 nicklas 22 package net.sf.basedb.util.overview.node;
4740 05 Feb 09 nicklas 23
4740 05 Feb 09 nicklas 24 import net.sf.basedb.core.BasicItem;
4740 05 Feb 09 nicklas 25 import net.sf.basedb.core.DbControl;
4740 05 Feb 09 nicklas 26 import net.sf.basedb.util.overview.Node;
4740 05 Feb 09 nicklas 27 import net.sf.basedb.util.overview.OverviewContext;
4766 17 Feb 09 nicklas 28 import net.sf.basedb.util.overview.cache.DirectionalCacheKey;
4740 05 Feb 09 nicklas 29 import net.sf.basedb.util.overview.cache.NodeCache;
4740 05 Feb 09 nicklas 30 import net.sf.basedb.util.overview.validator.NodeValidator;
4740 05 Feb 09 nicklas 31
4740 05 Feb 09 nicklas 32 /**
4740 05 Feb 09 nicklas 33   A node factory is responsible for creating item-type nodes.
4740 05 Feb 09 nicklas 34   The primary function of a node factory is to interface with
4740 05 Feb 09 nicklas 35   a {@link NodeValidator} to actually decide if a node should 
4740 05 Feb 09 nicklas 36   be created or not for a given item (which may be missing or
4740 05 Feb 09 nicklas 37   the current user may be denied access).
4740 05 Feb 09 nicklas 38   <p>
4740 05 Feb 09 nicklas 39   Another function is to interface with the current 
4740 05 Feb 09 nicklas 40   {@link OverviewContext} and it's optional {@link NodeCache}
4740 05 Feb 09 nicklas 41   so that we don't have to use resources for re-loading a deep
4740 05 Feb 09 nicklas 42   sub-tree starting with an item that has already been loaded
4740 05 Feb 09 nicklas 43   in another branch of the tree.
4740 05 Feb 09 nicklas 44   
4740 05 Feb 09 nicklas 45   @author Nicklas
4740 05 Feb 09 nicklas 46   @version 2.10
4740 05 Feb 09 nicklas 47   @base.modified $Date$
4740 05 Feb 09 nicklas 48 */
4740 05 Feb 09 nicklas 49 public class NodeFactory<I extends BasicItem>
4740 05 Feb 09 nicklas 50 {
6444 09 Apr 14 nicklas 51   private static final org.slf4j.Logger log = 
6444 09 Apr 14 nicklas 52     org.slf4j.LoggerFactory.getLogger(NodeFactory.class);
4740 05 Feb 09 nicklas 53   private static final boolean debug = log.isDebugEnabled();
4740 05 Feb 09 nicklas 54
4740 05 Feb 09 nicklas 55   private DbControl dc;
4740 05 Feb 09 nicklas 56   private OverviewContext context;
4740 05 Feb 09 nicklas 57   private NodeValidator<? super I> validator;
4740 05 Feb 09 nicklas 58   private NodeNameGenerator<? super I> nameGenerator;
4740 05 Feb 09 nicklas 59   
4740 05 Feb 09 nicklas 60   /**
4740 05 Feb 09 nicklas 61     Create a node factory. If a validator is specified it will be
4740 05 Feb 09 nicklas 62     used to determine if a node should be created or not. Without
4740 05 Feb 09 nicklas 63     a validator nodes are not created for missing items, only for
4740 05 Feb 09 nicklas 64     existing item (including if access is denied)
4740 05 Feb 09 nicklas 65     
4740 05 Feb 09 nicklas 66     @param dc A DbControl to use if database access is needed
4740 05 Feb 09 nicklas 67     @param context The current overview context
4740 05 Feb 09 nicklas 68     @param validator An optional validator
4740 05 Feb 09 nicklas 69     @param nameGenerator A name generator to use for node name and title
4740 05 Feb 09 nicklas 70       generation
4740 05 Feb 09 nicklas 71   */
4740 05 Feb 09 nicklas 72   public NodeFactory(DbControl dc, OverviewContext context, 
4740 05 Feb 09 nicklas 73       NodeValidator<? super I> validator, NodeNameGenerator<? super I> nameGenerator)
4740 05 Feb 09 nicklas 74   {
4740 05 Feb 09 nicklas 75     this.dc = dc;
4740 05 Feb 09 nicklas 76     this.context = context;
4740 05 Feb 09 nicklas 77     this.validator = validator;
4740 05 Feb 09 nicklas 78     this.nameGenerator = nameGenerator;
4740 05 Feb 09 nicklas 79   }
4740 05 Feb 09 nicklas 80   
4740 05 Feb 09 nicklas 81   /**
4740 05 Feb 09 nicklas 82     Get the node validator that is used by this factory.
4740 05 Feb 09 nicklas 83     @return A node validator or null if no validator is used
4740 05 Feb 09 nicklas 84   */
4740 05 Feb 09 nicklas 85   public NodeValidator<? super I> getNodeValidator()
4740 05 Feb 09 nicklas 86   {
4740 05 Feb 09 nicklas 87     return validator;
4740 05 Feb 09 nicklas 88   }
4740 05 Feb 09 nicklas 89   
4740 05 Feb 09 nicklas 90   /**
4740 05 Feb 09 nicklas 91     Create a node representing a missing item. A node is only created
4740 05 Feb 09 nicklas 92     if a validator is present and it's {@link 
4740 05 Feb 09 nicklas 93     NodeValidator#preMissingItem(DbControl, OverviewContext, Node)}
4740 05 Feb 09 nicklas 94     method returns TRUE.
4740 05 Feb 09 nicklas 95
4740 05 Feb 09 nicklas 96     @param parentNode The parent node
4740 05 Feb 09 nicklas 97     @return The new node, or null if no node was created
4740 05 Feb 09 nicklas 98   */
4740 05 Feb 09 nicklas 99   public Node createMissingNode(Node parentNode)
4740 05 Feb 09 nicklas 100   {
4740 05 Feb 09 nicklas 101     Node node = null;
4740 05 Feb 09 nicklas 102     if (validator != null && validator.preMissingItem(dc, context, parentNode))
4740 05 Feb 09 nicklas 103     {
4740 05 Feb 09 nicklas 104       String nodeName = nameGenerator.getMissingNodeName(parentNode);
4740 05 Feb 09 nicklas 105       String nodeTitle = nameGenerator.getMissingNodeTitle(parentNode);
4740 05 Feb 09 nicklas 106       node = createNode(null, nodeName, nodeTitle, null, parentNode, ChildNodeDirection.NONE);
4740 05 Feb 09 nicklas 107       validator.postMissingItem(dc, context, node, parentNode);
4740 05 Feb 09 nicklas 108     }
4740 05 Feb 09 nicklas 109     return node;
4740 05 Feb 09 nicklas 110   }
4740 05 Feb 09 nicklas 111   
4740 05 Feb 09 nicklas 112   /**
4740 05 Feb 09 nicklas 113     Create a node representing an item that the logged in user is denied to
4740 05 Feb 09 nicklas 114     access. A node is created if no validator is present or if the
4740 05 Feb 09 nicklas 115     validator's {@link 
4740 05 Feb 09 nicklas 116     NodeValidator#preDeniedItem(DbControl, OverviewContext, Node)}
4740 05 Feb 09 nicklas 117     method returns TRUE.
4740 05 Feb 09 nicklas 118   
4740 05 Feb 09 nicklas 119     @param parentNode The parent node
4740 05 Feb 09 nicklas 120     @return The new node, or null if no node was created
4740 05 Feb 09 nicklas 121   */
4740 05 Feb 09 nicklas 122   public Node createDeniedNode(Node parentNode)
4740 05 Feb 09 nicklas 123   {
4740 05 Feb 09 nicklas 124     Node node = null;
4740 05 Feb 09 nicklas 125     if (validator == null || validator.preDeniedItem(dc, context, parentNode))
4740 05 Feb 09 nicklas 126     {
4740 05 Feb 09 nicklas 127       String nodeName = nameGenerator.getDeniedNodeName(parentNode);
4740 05 Feb 09 nicklas 128       String nodeTitle = nameGenerator.getDeniedNodeTitle(parentNode);
4740 05 Feb 09 nicklas 129       node = createNode(null, nodeName, nodeTitle, null, parentNode, ChildNodeDirection.NONE);
4740 05 Feb 09 nicklas 130       if (validator != null) validator.postDeniedItem(dc, context, node, parentNode);
4740 05 Feb 09 nicklas 131     }
4740 05 Feb 09 nicklas 132     return node;
4740 05 Feb 09 nicklas 133   }
4740 05 Feb 09 nicklas 134   
4740 05 Feb 09 nicklas 135   /**
4740 05 Feb 09 nicklas 136     Create a node representing an existing item. A node is created if no 
4740 05 Feb 09 nicklas 137     validator is present or if the validator's {@link 
4740 05 Feb 09 nicklas 138     NodeValidator#preValidate(DbControl, OverviewContext, Object, Node)}
4740 05 Feb 09 nicklas 139     method returns TRUE.
4740 05 Feb 09 nicklas 140     
4740 05 Feb 09 nicklas 141     @param item The item to attach to the node
4740 05 Feb 09 nicklas 142     @param cacheKey An optional cache key
4740 05 Feb 09 nicklas 143     @param parentNode The parent node
4740 05 Feb 09 nicklas 144     @param direction The direction to use when loading the node's children
4740 05 Feb 09 nicklas 145     @return The new node, or null if no node was created
4740 05 Feb 09 nicklas 146   */
4740 05 Feb 09 nicklas 147   public Node createNode(I item, Object cacheKey, Node parentNode, ChildNodeDirection direction)
4740 05 Feb 09 nicklas 148   {
4740 05 Feb 09 nicklas 149     Node node = null;
4740 05 Feb 09 nicklas 150     if (validator == null || validator.preValidate(dc, context, item, parentNode))
4740 05 Feb 09 nicklas 151     {
4740 05 Feb 09 nicklas 152       String nodeName = nameGenerator.getNodeName(item, parentNode);
4740 05 Feb 09 nicklas 153       String nodeTitle = nameGenerator.getNodeTitle(item, parentNode);
4740 05 Feb 09 nicklas 154       node = createNode(item, nodeName, nodeTitle, cacheKey, parentNode, direction);
4740 05 Feb 09 nicklas 155       if (validator != null) validator.postValidate(dc, context, node, parentNode);
4740 05 Feb 09 nicklas 156     }
4740 05 Feb 09 nicklas 157     return node;
4740 05 Feb 09 nicklas 158   }
4740 05 Feb 09 nicklas 159
4740 05 Feb 09 nicklas 160   private Node createNode(I item, String name, String title, Object cacheKey, Node parentNode, ChildNodeDirection direction)
4740 05 Feb 09 nicklas 161   {
4740 05 Feb 09 nicklas 162     Node node = null;
4740 05 Feb 09 nicklas 163     if (cacheKey != null)
4740 05 Feb 09 nicklas 164     {
4766 17 Feb 09 nicklas 165       node = cloneCachedNode(cacheKey, parentNode, direction);
4740 05 Feb 09 nicklas 166     }
4740 05 Feb 09 nicklas 167     if (node == null)
4740 05 Feb 09 nicklas 168     {
4740 05 Feb 09 nicklas 169       node = new Node(name, title, parentNode, item, direction);
4766 17 Feb 09 nicklas 170       if (cacheKey != null) cacheNewNode(cacheKey, node, direction);
4740 05 Feb 09 nicklas 171     }
4740 05 Feb 09 nicklas 172     return node;
4740 05 Feb 09 nicklas 173   }
4740 05 Feb 09 nicklas 174   
4740 05 Feb 09 nicklas 175   /**
4740 05 Feb 09 nicklas 176     Clones a cached node if the current context supports
4740 05 Feb 09 nicklas 177     caching and another node with the given cache key 
4768 18 Feb 09 nicklas 178     already exists. This method wraps the given cacheKey 
4768 18 Feb 09 nicklas 179     with a {@link DirectionalCacheKey} since the loading
4768 18 Feb 09 nicklas 180     direction will affect the children of a node.
4740 05 Feb 09 nicklas 181     
4740 05 Feb 09 nicklas 182     @param cacheKey The cache key to use for node lookup
4740 05 Feb 09 nicklas 183     @param parentNode The node that should be the parent of the
4740 05 Feb 09 nicklas 184       cloned node
4766 17 Feb 09 nicklas 185     @param direction The direction we are loading child nodes in
4740 05 Feb 09 nicklas 186     @return The new (cloned) node, or null if no cached node was found
4740 05 Feb 09 nicklas 187     @see OverviewContext#getNodeCache()
4740 05 Feb 09 nicklas 188   */
4766 17 Feb 09 nicklas 189   protected Node cloneCachedNode(Object cacheKey, Node parentNode, ChildNodeDirection direction)
4740 05 Feb 09 nicklas 190   {
4740 05 Feb 09 nicklas 191     NodeCache<Object> cache = context.getNodeCache();
4740 05 Feb 09 nicklas 192     if (cache == null) return null;
4766 17 Feb 09 nicklas 193     Node node = cache.getNode(new DirectionalCacheKey(cacheKey, direction));
4740 05 Feb 09 nicklas 194     if (node != null) 
4740 05 Feb 09 nicklas 195     {
4740 05 Feb 09 nicklas 196       if (debug) log.debug("Cloning node: " + node + "; parent=" + parentNode);
4740 05 Feb 09 nicklas 197       node = node.deepCopy(parentNode);
4740 05 Feb 09 nicklas 198     }
4740 05 Feb 09 nicklas 199     return node;
4740 05 Feb 09 nicklas 200   }
4740 05 Feb 09 nicklas 201   
4740 05 Feb 09 nicklas 202   /**
4740 05 Feb 09 nicklas 203     Store a node in the node cache if the current overview context
4740 05 Feb 09 nicklas 204     supports caching.
4740 05 Feb 09 nicklas 205     
4740 05 Feb 09 nicklas 206     @param cacheKey The cache key
4740 05 Feb 09 nicklas 207     @param node The node to store
4766 17 Feb 09 nicklas 208     @param direction The direction we are loading child nodes in
4740 05 Feb 09 nicklas 209     @see OverviewContext#getNodeCache()
4740 05 Feb 09 nicklas 210   */
4766 17 Feb 09 nicklas 211   protected void cacheNewNode(Object cacheKey, Node node, ChildNodeDirection direction)
4740 05 Feb 09 nicklas 212   {
4740 05 Feb 09 nicklas 213     NodeCache<Object> cache = context.getNodeCache();
4740 05 Feb 09 nicklas 214     if (cache == null) return;
4766 17 Feb 09 nicklas 215     cache.putNode(new DirectionalCacheKey(cacheKey, direction), node);
4740 05 Feb 09 nicklas 216   }
4740 05 Feb 09 nicklas 217
4740 05 Feb 09 nicklas 218   public void postValidateFolder(Node folderNode, Node parentNode)
4740 05 Feb 09 nicklas 219   {
4740 05 Feb 09 nicklas 220     if (validator != null)
4740 05 Feb 09 nicklas 221     {
4740 05 Feb 09 nicklas 222       validator.postValidateFolder(dc, context, folderNode, parentNode);
4740 05 Feb 09 nicklas 223     }
4740 05 Feb 09 nicklas 224   }
4740 05 Feb 09 nicklas 225 }