src/core/net/sf/basedb/util/overview/loader/SampleLoader.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.loader;
4740 05 Feb 09 nicklas 23
5663 22 Jun 11 nicklas 24 import java.util.Iterator;
5663 22 Jun 11 nicklas 25
4740 05 Feb 09 nicklas 26 import net.sf.basedb.core.BioSource;
4740 05 Feb 09 nicklas 27 import net.sf.basedb.core.DbControl;
4740 05 Feb 09 nicklas 28 import net.sf.basedb.core.Extract;
4740 05 Feb 09 nicklas 29 import net.sf.basedb.core.Item;
4740 05 Feb 09 nicklas 30 import net.sf.basedb.core.ItemQuery;
4740 05 Feb 09 nicklas 31 import net.sf.basedb.core.ItemResultIterator;
5985 24 Feb 12 nicklas 32 import net.sf.basedb.core.ItemSubtype;
5663 22 Jun 11 nicklas 33 import net.sf.basedb.core.MeasuredBioMaterial;
4740 05 Feb 09 nicklas 34 import net.sf.basedb.core.PermissionDeniedException;
4740 05 Feb 09 nicklas 35 import net.sf.basedb.core.Sample;
4740 05 Feb 09 nicklas 36 import net.sf.basedb.util.overview.Fix;
4740 05 Feb 09 nicklas 37 import net.sf.basedb.util.overview.Node;
4740 05 Feb 09 nicklas 38 import net.sf.basedb.util.overview.OverviewContext;
4740 05 Feb 09 nicklas 39 import net.sf.basedb.util.overview.OverviewUtil;
4740 05 Feb 09 nicklas 40 import net.sf.basedb.util.overview.Validator;
4740 05 Feb 09 nicklas 41 import net.sf.basedb.util.overview.node.ChildNodeDirection;
4740 05 Feb 09 nicklas 42 import net.sf.basedb.util.overview.node.NameableNameGenerator;
4740 05 Feb 09 nicklas 43 import net.sf.basedb.util.overview.node.NodeFactory;
4740 05 Feb 09 nicklas 44
4740 05 Feb 09 nicklas 45 /**
4740 05 Feb 09 nicklas 46   Node loader implementation for samples. The forward-loading
4740 05 Feb 09 nicklas 47   direction goes from {@link BioSource}:s -&gt; {@link Sample}:s -&gt; 
4740 05 Feb 09 nicklas 48   {@link Extract}:s. The reverse-loading direction is the opposite 
4740 05 Feb 09 nicklas 49   direction. In both cases we also need to consider pooled samples.
4740 05 Feb 09 nicklas 50
4740 05 Feb 09 nicklas 51   @author Nicklas
4740 05 Feb 09 nicklas 52   @version 2.10
4740 05 Feb 09 nicklas 53   @base.modified $Date$
4740 05 Feb 09 nicklas 54 */
4740 05 Feb 09 nicklas 55 public class SampleLoader
4740 05 Feb 09 nicklas 56   extends BasicItemNodeLoader<Sample>
4740 05 Feb 09 nicklas 57 {
4740 05 Feb 09 nicklas 58
4740 05 Feb 09 nicklas 59   public SampleLoader()
4740 05 Feb 09 nicklas 60   {
4740 05 Feb 09 nicklas 61     super(Item.SAMPLE, ALLOW_ROOT_NODE, 
4740 05 Feb 09 nicklas 62         new NameableNameGenerator<Sample>("sample", "Sample"));
4740 05 Feb 09 nicklas 63   }
4740 05 Feb 09 nicklas 64   
4740 05 Feb 09 nicklas 65   /*
4740 05 Feb 09 nicklas 66     From the NodeLoader interface
4740 05 Feb 09 nicklas 67     ------------------------------
4740 05 Feb 09 nicklas 68   */
4740 05 Feb 09 nicklas 69   /**
4740 05 Feb 09 nicklas 70     Create forward-loading sample nodes from a given parent biosource
4740 05 Feb 09 nicklas 71     or sample. In both cases the returned node is a folder-type node
6043 03 Apr 12 nicklas 72     that contains the child samples. It can also create all-loading
6043 03 Apr 12 nicklas 73     node from a biomaterial list for the member samples.
6043 03 Apr 12 nicklas 74     @return The folder node for the samples (or null if used with a list)
4740 05 Feb 09 nicklas 75   */
4740 05 Feb 09 nicklas 76   @Override
4740 05 Feb 09 nicklas 77   public Node createForwardNode(DbControl dc, OverviewContext context, Node parentNode)
4740 05 Feb 09 nicklas 78   {
4740 05 Feb 09 nicklas 79     Node returnNode = null;
4740 05 Feb 09 nicklas 80     Item parentType = parentNode.getItemType();
4740 05 Feb 09 nicklas 81     if (parentType == Item.BIOSOURCE)
4740 05 Feb 09 nicklas 82     {
5985 24 Feb 12 nicklas 83       returnNode = createForwardNode((BioSource)parentNode.getItem(dc), dc, context, parentNode, false);
4740 05 Feb 09 nicklas 84     }
4740 05 Feb 09 nicklas 85     else if (parentType == Item.SAMPLE)
4740 05 Feb 09 nicklas 86     {
5985 24 Feb 12 nicklas 87       returnNode = createForwardNode((Sample)parentNode.getItem(dc), dc, context, parentNode, false);
4740 05 Feb 09 nicklas 88     }
6755 20 Feb 15 nicklas 89     else if (parentType == Item.ITEMLIST)
6755 20 Feb 15 nicklas 90     {
6755 20 Feb 15 nicklas 91       ItemListLoader.loadMemberNodes(this, dc, context, parentNode);
6755 20 Feb 15 nicklas 92     }
4740 05 Feb 09 nicklas 93     return returnNode;
4740 05 Feb 09 nicklas 94   }
4740 05 Feb 09 nicklas 95   
4740 05 Feb 09 nicklas 96   /**
4740 05 Feb 09 nicklas 97     Create reverse-loading sample nodes from an extract node
4740 05 Feb 09 nicklas 98     or from a pooled sample. In the first case, the returned node is an
4740 05 Feb 09 nicklas 99     item-type node with the parent sample. In the second case, the returned
4740 05 Feb 09 nicklas 100     node is a folder-type node with the pooled samples. 
4740 05 Feb 09 nicklas 101     @return A folder-type or item-type node
4740 05 Feb 09 nicklas 102   */
4740 05 Feb 09 nicklas 103   @Override
4740 05 Feb 09 nicklas 104   public Node createReverseNode(DbControl dc, OverviewContext context, Node parentNode)
4740 05 Feb 09 nicklas 105   {
4740 05 Feb 09 nicklas 106     Node returnNode = null;
4740 05 Feb 09 nicklas 107     Item parentType = parentNode.getItemType();
4740 05 Feb 09 nicklas 108     if (parentType == Item.EXTRACT)
4740 05 Feb 09 nicklas 109     {
5663 22 Jun 11 nicklas 110       returnNode = createSingleParentReverseNode((Extract)parentNode.getItem(dc), dc, context, parentNode);
4740 05 Feb 09 nicklas 111     }
4740 05 Feb 09 nicklas 112     else if (parentType == Item.SAMPLE)
4740 05 Feb 09 nicklas 113     {
5663 22 Jun 11 nicklas 114       Sample s = (Sample)parentNode.getItem(dc);
5663 22 Jun 11 nicklas 115       if (s.hasSingleParent())
5663 22 Jun 11 nicklas 116       {
5807 14 Oct 11 nicklas 117         returnNode = createSingleParentReverseNode(s, dc, context, parentNode);
5663 22 Jun 11 nicklas 118       }
5663 22 Jun 11 nicklas 119       else
5663 22 Jun 11 nicklas 120       {
5663 22 Jun 11 nicklas 121         returnNode = createPooledReverseNode(s, dc, context, parentNode);
5663 22 Jun 11 nicklas 122       }
4740 05 Feb 09 nicklas 123     }
4740 05 Feb 09 nicklas 124     return returnNode;
4740 05 Feb 09 nicklas 125   }
5985 24 Feb 12 nicklas 126   
5985 24 Feb 12 nicklas 127   /**
5985 24 Feb 12 nicklas 128     A property node is created when moving in the reverse direction so that we
5985 24 Feb 12 nicklas 129     can load child samples+extracts with the {@link ItemSubtype#getPushAnnotations()} 
5985 24 Feb 12 nicklas 130     flag set. The parent node should be a biosource or sample node.
5985 24 Feb 12 nicklas 131     @since 3.1
5985 24 Feb 12 nicklas 132   */
5985 24 Feb 12 nicklas 133   @Override
5985 24 Feb 12 nicklas 134   public Node createPropertyNode(DbControl dc, OverviewContext context, Node parentNode) 
5985 24 Feb 12 nicklas 135   {
5985 24 Feb 12 nicklas 136     Node returnNode = null;
5985 24 Feb 12 nicklas 137     Item parentType = parentNode.getItemType();
5985 24 Feb 12 nicklas 138     if (parentType == Item.BIOSOURCE)
5985 24 Feb 12 nicklas 139     {
5985 24 Feb 12 nicklas 140       returnNode = createForwardNode((BioSource)parentNode.getItem(dc), dc, context, parentNode, true);
5985 24 Feb 12 nicklas 141     }
5985 24 Feb 12 nicklas 142     else if (parentType == Item.SAMPLE)
5985 24 Feb 12 nicklas 143     {
5985 24 Feb 12 nicklas 144       returnNode = createForwardNode((Sample)parentNode.getItem(dc), dc, context, parentNode, true);
5985 24 Feb 12 nicklas 145     }
5985 24 Feb 12 nicklas 146     return returnNode;
5985 24 Feb 12 nicklas 147   }
4740 05 Feb 09 nicklas 148   // --------------------------------
4740 05 Feb 09 nicklas 149   /*
4740 05 Feb 09 nicklas 150     From the AbstractNodeLoader class
4740 05 Feb 09 nicklas 151     ----------------------------------
4740 05 Feb 09 nicklas 152   */
4740 05 Feb 09 nicklas 153   /**
4740 05 Feb 09 nicklas 154     Loads property nodes of a sample. 
4740 05 Feb 09 nicklas 155     <ul>
4740 05 Feb 09 nicklas 156     <li>Annotations: {@link AnnotationLoader#createPropertyNode(DbControl, OverviewContext, Node)}
6041 02 Apr 12 nicklas 157     <li>Bioplate/well: {@link BioPlateLoader#createPropertyNode(DbControl, OverviewContext, Node)}
4740 05 Feb 09 nicklas 158     <li>Protocol: {@link ProtocolLoader#createPropertyNode(DbControl, OverviewContext, Node)}
7004 09 Nov 15 nicklas 159     <li>Kit: {@link KitLoader#createPropertyNode(DbControl, OverviewContext, Node)}
4740 05 Feb 09 nicklas 160     </ul>
4740 05 Feb 09 nicklas 161   */
4740 05 Feb 09 nicklas 162   @Override
4740 05 Feb 09 nicklas 163   protected void loadPropertyChildNodes(DbControl dc, OverviewContext context, Node sampleNode)
4740 05 Feb 09 nicklas 164   {
6042 03 Apr 12 nicklas 165     Node parentNode = sampleNode.getParent();
4740 05 Feb 09 nicklas 166     getNodeLoader(context, Item.ANNOTATION).createPropertyNode(dc, context, sampleNode);
6042 03 Apr 12 nicklas 167     if (parentNode == null || parentNode.getItemType() != Item.BIOPLATE)
6042 03 Apr 12 nicklas 168     {
6042 03 Apr 12 nicklas 169       // Do not load the bioplate if we just started from it
6042 03 Apr 12 nicklas 170       getNodeLoader(context, Item.BIOPLATE).createPropertyNode(dc, context, sampleNode);
6042 03 Apr 12 nicklas 171     }
4740 05 Feb 09 nicklas 172     getNodeLoader(context, Item.PROTOCOL).createPropertyNode(dc, context, sampleNode);
7004 09 Nov 15 nicklas 173     getNodeLoader(context, Item.KIT).createPropertyNode(dc, context, sampleNode);
5500 18 Nov 10 nicklas 174     getNodeLoader(context, Item.ANYTOANY).createPropertyNode(dc, context, sampleNode);
4740 05 Feb 09 nicklas 175   }
4740 05 Feb 09 nicklas 176
4740 05 Feb 09 nicklas 177   /**
4740 05 Feb 09 nicklas 178     Loads the pooled samples and extracts that has been created from
4740 05 Feb 09 nicklas 179     this sample.
4740 05 Feb 09 nicklas 180     @see ExtractLoader#createForwardNode(DbControl, OverviewContext, Node)
4740 05 Feb 09 nicklas 181     @see SampleLoader#createForwardNode(DbControl, OverviewContext, Node)
4740 05 Feb 09 nicklas 182   */
4740 05 Feb 09 nicklas 183   @Override
4740 05 Feb 09 nicklas 184   protected void loadForwardChildNodes(DbControl dc, OverviewContext context, Node sampleNode)
4740 05 Feb 09 nicklas 185   {
4740 05 Feb 09 nicklas 186     getNodeLoader(context, Item.EXTRACT).createForwardNode(dc, context, sampleNode);
4740 05 Feb 09 nicklas 187     getNodeLoader(context, Item.SAMPLE).createForwardNode(dc, context, sampleNode);
4740 05 Feb 09 nicklas 188   }
4740 05 Feb 09 nicklas 189   
4740 05 Feb 09 nicklas 190   /**
4740 05 Feb 09 nicklas 191     If the sample is a pooled sample, loads the parent samples that
5985 24 Feb 12 nicklas 192     it was pooled from. Otherwise load the parent biosource. Also load
5985 24 Feb 12 nicklas 193     any child samples or extracts that have a subtype with the
5985 24 Feb 12 nicklas 194     {@link ItemSubtype#getPushAnnotations()} flag set.
4740 05 Feb 09 nicklas 195     @see SampleLoader#createReverseNode(DbControl, OverviewContext, Node)
4740 05 Feb 09 nicklas 196     @see BioSourceLoader#createReverseNode(DbControl, OverviewContext, Node)
4740 05 Feb 09 nicklas 197   */
4740 05 Feb 09 nicklas 198   @Override
4740 05 Feb 09 nicklas 199   protected void loadReverseChildNodes(DbControl dc, OverviewContext context, Node sampleNode)
4740 05 Feb 09 nicklas 200   {
5748 19 Sep 11 nicklas 201     Sample sample = (Sample)sampleNode.getItem(dc);
5663 22 Jun 11 nicklas 202     if (sample.getParentType() == Item.SAMPLE)
4740 05 Feb 09 nicklas 203     {
4740 05 Feb 09 nicklas 204       getNodeLoader(context, Item.SAMPLE).createReverseNode(dc, context, sampleNode);
4740 05 Feb 09 nicklas 205     }
4740 05 Feb 09 nicklas 206     else
4740 05 Feb 09 nicklas 207     {
4740 05 Feb 09 nicklas 208       getNodeLoader(context, Item.BIOSOURCE).createReverseNode(dc, context, sampleNode);
4740 05 Feb 09 nicklas 209     }
5985 24 Feb 12 nicklas 210     if (sampleNode.getChildNodeDirection() == ChildNodeDirection.REVERSE)
5985 24 Feb 12 nicklas 211     {
5985 24 Feb 12 nicklas 212       // Only if we are moving in the reverse direction (eg. not when the sample is a root node)
5985 24 Feb 12 nicklas 213       getNodeLoader(context, Item.SAMPLE).createPropertyNode(dc, context, sampleNode);
5985 24 Feb 12 nicklas 214       getNodeLoader(context, Item.EXTRACT).createPropertyNode(dc, context, sampleNode);
5985 24 Feb 12 nicklas 215     }
4740 05 Feb 09 nicklas 216   }
4740 05 Feb 09 nicklas 217   // ---------------------------------------
4740 05 Feb 09 nicklas 218   
4740 05 Feb 09 nicklas 219   /**
5663 22 Jun 11 nicklas 220     Create reverse-loading samples nodes of a sample with other sample(s) as parent items. 
5663 22 Jun 11 nicklas 221     Eg. the child nodes are the source sample(s) that was used to create the given product.
4740 05 Feb 09 nicklas 222   */
5663 22 Jun 11 nicklas 223   private Node createPooledReverseNode(Sample product, DbControl dc, OverviewContext context, Node parentNode)
4740 05 Feb 09 nicklas 224   {
4740 05 Feb 09 nicklas 225     NodeFactory<Sample> nf = getNodeFactory(dc, context);
4740 05 Feb 09 nicklas 226     Node folderNode = null;
7605 26 Feb 19 nicklas 227     ItemQuery<Sample> query = context.initQuery(product.getCreationEvent().getSources(), "name");
5663 22 Jun 11 nicklas 228     Iterator<Sample> it = query.iterate(dc);
4753 12 Feb 09 nicklas 229     int numSamples = 0;
4740 05 Feb 09 nicklas 230     while (it.hasNext())
4740 05 Feb 09 nicklas 231     {
4753 12 Feb 09 nicklas 232       numSamples++;
4740 05 Feb 09 nicklas 233       Sample source = it.next();
4740 05 Feb 09 nicklas 234       // We need to handle circular references inline because
4740 05 Feb 09 nicklas 235       // we can never require that a validator implementation handles this
4753 12 Feb 09 nicklas 236       Node circularNode = OverviewUtil.getCircularRef(parentNode, source);
4753 12 Feb 09 nicklas 237       if (circularNode != null)
4740 05 Feb 09 nicklas 238       {
4740 05 Feb 09 nicklas 239         context.createFailure(Validator.CIRCULAR_REFERENCE, parentNode, 
4740 05 Feb 09 nicklas 240             "Circular reference to '" + source.getName() + "'", 
4753 12 Feb 09 nicklas 241             new Fix("Modify parent samples of '" + product.getName() + "'", product),
4753 12 Feb 09 nicklas 242             new Fix("Modify parent samples of '" + source.getName() + "'", source)
4740 05 Feb 09 nicklas 243           );
4740 05 Feb 09 nicklas 244       }
4740 05 Feb 09 nicklas 245       else
4740 05 Feb 09 nicklas 246       {
4740 05 Feb 09 nicklas 247         if (folderNode == null)
4740 05 Feb 09 nicklas 248         {
4753 12 Feb 09 nicklas 249           folderNode = new Node("pooled", "Parent samples", parentNode, ChildNodeDirection.REVERSE);
4740 05 Feb 09 nicklas 250         }
4766 17 Feb 09 nicklas 251         createItemNode(nf, source, source, false, folderNode, ChildNodeDirection.REVERSE);
4740 05 Feb 09 nicklas 252       }
4740 05 Feb 09 nicklas 253     }
4753 12 Feb 09 nicklas 254     postValidateFolder(nf, folderNode, parentNode, numSamples == 0);
4740 05 Feb 09 nicklas 255     return folderNode;
4740 05 Feb 09 nicklas 256   }
4740 05 Feb 09 nicklas 257
4740 05 Feb 09 nicklas 258   /**
5663 22 Jun 11 nicklas 259     Create a reverse-loading sample node from an extract or sample. Eg. the child node
5663 22 Jun 11 nicklas 260     is the sample that is the parent of the (non-pooled) extract/sample.
4740 05 Feb 09 nicklas 261   */
5663 22 Jun 11 nicklas 262   private Node createSingleParentReverseNode(MeasuredBioMaterial bioMaterial, DbControl dc, OverviewContext context, Node parentNode)
4740 05 Feb 09 nicklas 263   {
4740 05 Feb 09 nicklas 264     NodeFactory<Sample> nf = getNodeFactory(dc, context);
4740 05 Feb 09 nicklas 265     Sample sample = null;
4740 05 Feb 09 nicklas 266     boolean denied = false;
4740 05 Feb 09 nicklas 267     try
4740 05 Feb 09 nicklas 268     {
5663 22 Jun 11 nicklas 269       sample = (Sample)bioMaterial.getParent();
4740 05 Feb 09 nicklas 270     }
4740 05 Feb 09 nicklas 271     catch (PermissionDeniedException ex)
4740 05 Feb 09 nicklas 272     {
4740 05 Feb 09 nicklas 273       denied = true;
4740 05 Feb 09 nicklas 274     }
4766 17 Feb 09 nicklas 275     Node sampleNode = createItemNode(nf, sample, sample, denied, 
4740 05 Feb 09 nicklas 276         parentNode, ChildNodeDirection.REVERSE);
4740 05 Feb 09 nicklas 277     return sampleNode;
4740 05 Feb 09 nicklas 278   }
4740 05 Feb 09 nicklas 279
4740 05 Feb 09 nicklas 280   /**
4740 05 Feb 09 nicklas 281     Create forward-loading sample nodes for the samples that has a given
4740 05 Feb 09 nicklas 282     biosource as their parent.
4740 05 Feb 09 nicklas 283   */
5985 24 Feb 12 nicklas 284   private Node createForwardNode(BioSource bioSource, DbControl dc, OverviewContext context, Node parentNode,
5985 24 Feb 12 nicklas 285     boolean onlyPushAnnotationTypes)
4740 05 Feb 09 nicklas 286   {
4740 05 Feb 09 nicklas 287     NodeFactory<Sample> nf = getNodeFactory(dc, context);
4740 05 Feb 09 nicklas 288     Node folderNode = null;
4740 05 Feb 09 nicklas 289     ItemQuery<Sample> query = context.initQuery(bioSource.getSamples(), "name");
5985 24 Feb 12 nicklas 290     if (onlyPushAnnotationTypes) OverviewUtil.restrictToPushAnnotationSubtypes(query);
4740 05 Feb 09 nicklas 291     ItemResultIterator<Sample> it = query.iterate(dc);
4740 05 Feb 09 nicklas 292     while (it.hasNext())
4740 05 Feb 09 nicklas 293     {
4740 05 Feb 09 nicklas 294       Sample sample = it.next();
4740 05 Feb 09 nicklas 295       if (folderNode == null)
4740 05 Feb 09 nicklas 296       {
4753 12 Feb 09 nicklas 297         folderNode = new Node("samples", "Child samples", parentNode, ChildNodeDirection.FORWARD);
4740 05 Feb 09 nicklas 298       }
4766 17 Feb 09 nicklas 299       createItemNode(nf, sample, sample, false, folderNode, ChildNodeDirection.FORWARD);
4740 05 Feb 09 nicklas 300     }
4740 05 Feb 09 nicklas 301     postValidateFolder(nf, folderNode, parentNode, false);
4740 05 Feb 09 nicklas 302     return folderNode;
4740 05 Feb 09 nicklas 303   }
4740 05 Feb 09 nicklas 304   
6042 03 Apr 12 nicklas 305   
4740 05 Feb 09 nicklas 306   /**
4740 05 Feb 09 nicklas 307     Create forward-loading sample nodes for the (pooled) samples that has a given
4740 05 Feb 09 nicklas 308     sample as their parent.
4740 05 Feb 09 nicklas 309   */
5985 24 Feb 12 nicklas 310   private Node createForwardNode(Sample parentSample, DbControl dc, OverviewContext context, Node parentNode,
5985 24 Feb 12 nicklas 311     boolean onlyPushAnnotationTypes)
4740 05 Feb 09 nicklas 312   {
4740 05 Feb 09 nicklas 313     NodeFactory<Sample> nf = getNodeFactory(dc, context);
4740 05 Feb 09 nicklas 314     Node folderNode = null;
4740 05 Feb 09 nicklas 315     ItemQuery<Sample> query = context.initQuery(parentSample.getChildSamples(), "name");
5985 24 Feb 12 nicklas 316     if (onlyPushAnnotationTypes) OverviewUtil.restrictToPushAnnotationSubtypes(query);
4740 05 Feb 09 nicklas 317     ItemResultIterator<Sample> it = query.iterate(dc);
4740 05 Feb 09 nicklas 318     while (it.hasNext())
4740 05 Feb 09 nicklas 319     {
4740 05 Feb 09 nicklas 320       Sample childSample = it.next();
4740 05 Feb 09 nicklas 321       // We need to handle circular references inline because
4740 05 Feb 09 nicklas 322       // we can never require that a validator implementation handles this
4740 05 Feb 09 nicklas 323       Node circularNode = OverviewUtil.getCircularRef(parentNode, childSample);
4740 05 Feb 09 nicklas 324       if (circularNode != null)
4740 05 Feb 09 nicklas 325       {
4753 12 Feb 09 nicklas 326         context.createFailure(Validator.CIRCULAR_REFERENCE, parentNode, 
4753 12 Feb 09 nicklas 327           "Circular reference to '" + childSample.getName() + "'", 
4753 12 Feb 09 nicklas 328           new Fix("Modify parent samples of '" + childSample.getName() + "'", childSample),
4753 12 Feb 09 nicklas 329           new Fix("Modify parent samples of '" + parentSample.getName() + "'", parentSample)
4740 05 Feb 09 nicklas 330           );
4740 05 Feb 09 nicklas 331       }
4740 05 Feb 09 nicklas 332       else
4740 05 Feb 09 nicklas 333       {
4740 05 Feb 09 nicklas 334         if (folderNode == null)
4740 05 Feb 09 nicklas 335         {
4753 12 Feb 09 nicklas 336           folderNode = new Node("samples", "Child samples", parentNode, ChildNodeDirection.FORWARD);
4740 05 Feb 09 nicklas 337         }
4766 17 Feb 09 nicklas 338         createItemNode(nf, childSample, childSample, false, folderNode, ChildNodeDirection.FORWARD);
4740 05 Feb 09 nicklas 339       }
4740 05 Feb 09 nicklas 340     }    
4740 05 Feb 09 nicklas 341     postValidateFolder(nf, folderNode, parentNode, false);
4740 05 Feb 09 nicklas 342     return folderNode;
4740 05 Feb 09 nicklas 343   }
4740 05 Feb 09 nicklas 344   
4740 05 Feb 09 nicklas 345 }