src/core/net/sf/basedb/util/overview/validator/ExtractValidator.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.validator;
4740 05 Feb 09 nicklas 23
6098 03 Sep 12 nicklas 24 import java.util.Collections;
5807 14 Oct 11 nicklas 25 import java.util.HashMap;
5807 14 Oct 11 nicklas 26 import java.util.HashSet;
5807 14 Oct 11 nicklas 27 import java.util.Map;
5807 14 Oct 11 nicklas 28 import java.util.Set;
5807 14 Oct 11 nicklas 29
4740 05 Feb 09 nicklas 30 import net.sf.basedb.core.BasicItem;
5807 14 Oct 11 nicklas 31 import net.sf.basedb.core.BioMaterialEvent;
5807 14 Oct 11 nicklas 32 import net.sf.basedb.core.BioMaterialEventSource;
5651 08 Jun 11 nicklas 33 import net.sf.basedb.core.DbControl;
4740 05 Feb 09 nicklas 34 import net.sf.basedb.core.Extract;
6098 03 Sep 12 nicklas 35 import net.sf.basedb.core.Include;
4740 05 Feb 09 nicklas 36 import net.sf.basedb.core.Item;
6098 03 Sep 12 nicklas 37 import net.sf.basedb.core.ItemQuery;
5651 08 Jun 11 nicklas 38 import net.sf.basedb.core.ItemSubtype;
5651 08 Jun 11 nicklas 39 import net.sf.basedb.core.PermissionDeniedException;
5651 08 Jun 11 nicklas 40 import net.sf.basedb.core.PhysicalBioAssay;
5651 08 Jun 11 nicklas 41 import net.sf.basedb.core.Sample;
5807 14 Oct 11 nicklas 42 import net.sf.basedb.core.SpecialQuery;
5807 14 Oct 11 nicklas 43 import net.sf.basedb.core.Tag;
5807 14 Oct 11 nicklas 44 import net.sf.basedb.util.EqualsHelper;
6799 25 Mar 15 nicklas 45 import net.sf.basedb.util.listable.ExtractToParentExtractTransformer;
6799 25 Mar 15 nicklas 46 import net.sf.basedb.util.listable.SourceItemTransformer;
6799 25 Mar 15 nicklas 47 import net.sf.basedb.util.listable.TransformContext;
5807 14 Oct 11 nicklas 48 import net.sf.basedb.util.overview.Failure;
4740 05 Feb 09 nicklas 49 import net.sf.basedb.util.overview.Fix;
5651 08 Jun 11 nicklas 50 import net.sf.basedb.util.overview.OverviewContext;
4740 05 Feb 09 nicklas 51 import net.sf.basedb.util.overview.Validator;
4740 05 Feb 09 nicklas 52 import net.sf.basedb.util.overview.Node;
5651 08 Jun 11 nicklas 53 import net.sf.basedb.util.overview.node.ChildNodeDirection;
4740 05 Feb 09 nicklas 54
4740 05 Feb 09 nicklas 55 /**
4740 05 Feb 09 nicklas 56   Validator implementation for extracts. Validation rules:
4740 05 Feb 09 nicklas 57   <ul>
4740 05 Feb 09 nicklas 58   <li>Missing item: {@link Validator#MISSING_EXTRACT}
4740 05 Feb 09 nicklas 59   <li>Access denied: {@link Validator#DENIED_EXTRACT}
5651 08 Jun 11 nicklas 60   <li>Subtype of parent extract: {@link Validator#INCORRECT_EXTRACT_TYPE}
5651 08 Jun 11 nicklas 61   <li>Subtype of parent sample: {@link Validator#INCORRECT_SAMPLE_TYPE}
5807 14 Oct 11 nicklas 62   <li>Different tag than parent: {@link Validator#DIFFERENT_TAG}
5807 14 Oct 11 nicklas 63   <li>Parent is tagged, but child is not: {@link Validator#TAGGED_PARENT}
5807 14 Oct 11 nicklas 64   <li>Duplicates of same tag+position on bioassay: {@link Validator#NONUNIQUE_TAG}
5807 14 Oct 11 nicklas 65   <li>Incorrect position on bioassay: {@link Validator#INCORRECT_BIOASSAY_POSITION}
4740 05 Feb 09 nicklas 66   </ul>
4740 05 Feb 09 nicklas 67
4740 05 Feb 09 nicklas 68   @author Nicklas
4740 05 Feb 09 nicklas 69   @version 2.10
4740 05 Feb 09 nicklas 70   @base.modified $Date$
4740 05 Feb 09 nicklas 71 */
4740 05 Feb 09 nicklas 72 public class ExtractValidator
4764 16 Feb 09 nicklas 73   extends NameableNodeValidator<Extract>
4740 05 Feb 09 nicklas 74 {
4740 05 Feb 09 nicklas 75   
4740 05 Feb 09 nicklas 76   public ExtractValidator()
4740 05 Feb 09 nicklas 77   {
4740 05 Feb 09 nicklas 78     super(Validator.MISSING_EXTRACT, Validator.DENIED_EXTRACT);
4740 05 Feb 09 nicklas 79   }
4740 05 Feb 09 nicklas 80   
4740 05 Feb 09 nicklas 81   /* 
4740 05 Feb 09 nicklas 82     From BasicValidator class
4740 05 Feb 09 nicklas 83     -------------------------
4740 05 Feb 09 nicklas 84   */
5807 14 Oct 11 nicklas 85   /**
6959 01 Oct 15 nicklas 86     Do not report missing items if the parent node is a derived or (root) raw bioassay.
5807 14 Oct 11 nicklas 87    */
5651 08 Jun 11 nicklas 88   @Override
5807 14 Oct 11 nicklas 89   public boolean preMissingItem(DbControl dc, OverviewContext context, Node parentNode)
5807 14 Oct 11 nicklas 90   {
5807 14 Oct 11 nicklas 91     Item parentType = parentNode.getItemType();
6959 01 Oct 15 nicklas 92     if (parentType == Item.DERIVEDBIOASSAY || parentType == Item.RAWBIOASSAY || parentType == Item.ROOTRAWBIOASSAY) return false;
5807 14 Oct 11 nicklas 93     return super.preMissingItem(dc, context, parentNode);
5807 14 Oct 11 nicklas 94   }
5807 14 Oct 11 nicklas 95
5807 14 Oct 11 nicklas 96   @Override
5651 08 Jun 11 nicklas 97   public void postValidate(DbControl dc, OverviewContext context, Node node, Node parentNode) 
5651 08 Jun 11 nicklas 98   {
5651 08 Jun 11 nicklas 99     super.postValidate(dc, context, node, parentNode);
5651 08 Jun 11 nicklas 100
5651 08 Jun 11 nicklas 101     if (parentNode != null)
5651 08 Jun 11 nicklas 102     {
5807 14 Oct 11 nicklas 103       Node parentItemNode = parentNode.getNodeType() == Node.Type.ITEM ? parentNode : parentNode.getParent();
5651 08 Jun 11 nicklas 104       Item parentType = parentItemNode.getItemType();
5651 08 Jun 11 nicklas 105
5651 08 Jun 11 nicklas 106       if (parentType == Item.SAMPLE)
5651 08 Jun 11 nicklas 107       {
5651 08 Jun 11 nicklas 108         checkParentSampleSubtype(dc, context, node, parentItemNode);
5651 08 Jun 11 nicklas 109       }
5651 08 Jun 11 nicklas 110       else if (parentType == Item.EXTRACT)
5651 08 Jun 11 nicklas 111       {
5651 08 Jun 11 nicklas 112         if (node.getChildNodeDirection() == ChildNodeDirection.FORWARD)
5651 08 Jun 11 nicklas 113         {
5651 08 Jun 11 nicklas 114           checkParentExtractSubtype(dc, context, node, parentItemNode);
5807 14 Oct 11 nicklas 115           checkExtractTag(dc, context, node, parentItemNode);
5651 08 Jun 11 nicklas 116         }
5651 08 Jun 11 nicklas 117         else
5651 08 Jun 11 nicklas 118         {
5651 08 Jun 11 nicklas 119           checkParentExtractSubtype(dc, context, parentItemNode, node);
5807 14 Oct 11 nicklas 120           checkExtractTag(dc, context, parentItemNode, node);
5651 08 Jun 11 nicklas 121         }
5651 08 Jun 11 nicklas 122       }
5651 08 Jun 11 nicklas 123       else if (parentType == Item.PHYSICALBIOASSAY)
5651 08 Jun 11 nicklas 124       {
5651 08 Jun 11 nicklas 125         PhysicalBioAssayValidator.checkExtractSubtype(dc, context, parentItemNode, node);
5807 14 Oct 11 nicklas 126         checkExtractOnBioAssay(dc, context, node, parentItemNode);
5651 08 Jun 11 nicklas 127       }
5807 14 Oct 11 nicklas 128       else if (parentType == Item.DERIVEDBIOASSAY)
5807 14 Oct 11 nicklas 129       {
5807 14 Oct 11 nicklas 130         DerivedBioAssayValidator.checkExtractSubtype(dc, context, parentItemNode, node);
5807 14 Oct 11 nicklas 131       }
6042 03 Apr 12 nicklas 132       else if (parentType == Item.BIOPLATE)
6042 03 Apr 12 nicklas 133       {
6042 03 Apr 12 nicklas 134         BioPlateValidator.checkBioMaterialInWell(dc, context, parentItemNode, node);
6042 03 Apr 12 nicklas 135       }
5651 08 Jun 11 nicklas 136     }
5651 08 Jun 11 nicklas 137   }
5651 08 Jun 11 nicklas 138
5651 08 Jun 11 nicklas 139   
4740 05 Feb 09 nicklas 140   /**
5651 08 Jun 11 nicklas 141     The suggested fix is to add parent extracts to the physical
5651 08 Jun 11 nicklas 142     bioassay or one or more extracts to the pooled extract.
4740 05 Feb 09 nicklas 143   */
4740 05 Feb 09 nicklas 144   @Override
5651 08 Jun 11 nicklas 145   protected Fix getMissingItemFix(DbControl dc, Node parentNode)
4740 05 Feb 09 nicklas 146   {
4740 05 Feb 09 nicklas 147     Fix fix = null;
4740 05 Feb 09 nicklas 148     Item parentType = parentNode.getItemType();
4740 05 Feb 09 nicklas 149     BasicItem parentItem = parentNode.getItem();
5641 25 May 11 nicklas 150     if (parentType == Item.PHYSICALBIOASSAY)
4740 05 Feb 09 nicklas 151     {
5651 08 Jun 11 nicklas 152       fix =  new Fix("Add extracts to '" + ((PhysicalBioAssay)parentItem).getName() + "'", parentItem);
4740 05 Feb 09 nicklas 153     }
5651 08 Jun 11 nicklas 154     else if (parentType == Item.EXTRACT)
4740 05 Feb 09 nicklas 155     {
4755 12 Feb 09 nicklas 156       fix = new Fix("Add parent extracts to '" + ((Extract)parentItem).getName() + "'", parentItem);
4740 05 Feb 09 nicklas 157     }
4740 05 Feb 09 nicklas 158     return fix;
4740 05 Feb 09 nicklas 159   }
5807 14 Oct 11 nicklas 160   
5807 14 Oct 11 nicklas 161   /**
5807 14 Oct 11 nicklas 162     If the parent is a physical bioassay, check that extracts on the
5807 14 Oct 11 nicklas 163     same position has different tags.
5807 14 Oct 11 nicklas 164   */
5807 14 Oct 11 nicklas 165   @SuppressWarnings("unchecked")
5807 14 Oct 11 nicklas 166   @Override
5807 14 Oct 11 nicklas 167   public void postValidateFolder(DbControl dc, OverviewContext context, Node folderNode, Node parentNode)
5807 14 Oct 11 nicklas 168   {
5807 14 Oct 11 nicklas 169     super.postValidateFolder(dc, context, folderNode, parentNode);
5807 14 Oct 11 nicklas 170     if (parentNode.getItemType() != Item.PHYSICALBIOASSAY) return;
5807 14 Oct 11 nicklas 171
5807 14 Oct 11 nicklas 172     PhysicalBioAssay pba = (PhysicalBioAssay)parentNode.getItem(dc);
5807 14 Oct 11 nicklas 173     BioMaterialEvent creationEvent = pba.getCreationEvent();
5807 14 Oct 11 nicklas 174     
5807 14 Oct 11 nicklas 175     // Get all positions that are used by the child nodes
5807 14 Oct 11 nicklas 176     if (folderNode != null)
5807 14 Oct 11 nicklas 177     {
5807 14 Oct 11 nicklas 178       // Create a map of tag+position => extract(s)
5807 14 Oct 11 nicklas 179       Map<TagPosition, Set<Extract>> tagPositions = 
5807 14 Oct 11 nicklas 180           (Map<TagPosition, Set<Extract>>)context.getCachedObject("TAGPOSITIONS:" + pba.getId());
5807 14 Oct 11 nicklas 181       if (tagPositions == null)
5807 14 Oct 11 nicklas 182       {
5807 14 Oct 11 nicklas 183         tagPositions = new HashMap<ExtractValidator.TagPosition, Set<Extract>>();
5807 14 Oct 11 nicklas 184         context.setCachedObject("TAGPOSITIONS:" + pba.getId(), tagPositions);
5807 14 Oct 11 nicklas 185
5807 14 Oct 11 nicklas 186         SpecialQuery<BioMaterialEventSource> query = creationEvent.getEventSources();
5807 14 Oct 11 nicklas 187         for (BioMaterialEventSource src : query.list(dc))
5807 14 Oct 11 nicklas 188         {
5807 14 Oct 11 nicklas 189           try
5807 14 Oct 11 nicklas 190           {
5807 14 Oct 11 nicklas 191             Extract extract = (Extract)src.getBioMaterial();
5807 14 Oct 11 nicklas 192             Tag tag = extract.getTag();
5807 14 Oct 11 nicklas 193             int position = src.getPosition();
5807 14 Oct 11 nicklas 194             TagPosition tp = new TagPosition(tag, position);
5807 14 Oct 11 nicklas 195             Set<Extract> extracts = tagPositions.get(tp);
5807 14 Oct 11 nicklas 196             if (extracts == null)
5807 14 Oct 11 nicklas 197             {
5807 14 Oct 11 nicklas 198               // First extract with this tag+position
5807 14 Oct 11 nicklas 199               extracts = new HashSet<Extract>();
5807 14 Oct 11 nicklas 200               tagPositions.put(tp, extracts);
5807 14 Oct 11 nicklas 201             }
5807 14 Oct 11 nicklas 202             extracts.add(extract);
5807 14 Oct 11 nicklas 203           }
5807 14 Oct 11 nicklas 204           catch (PermissionDeniedException ex)
5807 14 Oct 11 nicklas 205           {}
5807 14 Oct 11 nicklas 206         }
5807 14 Oct 11 nicklas 207       }
5807 14 Oct 11 nicklas 208       
5807 14 Oct 11 nicklas 209       // Get the positions for the extracts in the current folder
5807 14 Oct 11 nicklas 210       Set<Integer> positions = new HashSet<Integer>();
5807 14 Oct 11 nicklas 211       for (Node extractNode : folderNode.getChildren())
5807 14 Oct 11 nicklas 212       {
5807 14 Oct 11 nicklas 213         Extract extract = (Extract)extractNode.getItem(dc);
5807 14 Oct 11 nicklas 214         BioMaterialEventSource src = creationEvent.getEventSource(extract);
5807 14 Oct 11 nicklas 215         positions.add(src.getPosition());
5807 14 Oct 11 nicklas 216       }
5807 14 Oct 11 nicklas 217
5807 14 Oct 11 nicklas 218       // Check in the map if there are any tag+positions with more than one extract
5807 14 Oct 11 nicklas 219       for (Map.Entry<TagPosition, Set<Extract>> entry : tagPositions.entrySet())
5807 14 Oct 11 nicklas 220       {
5807 14 Oct 11 nicklas 221         Set<Extract> extracts = entry.getValue();
5807 14 Oct 11 nicklas 222         TagPosition tp = entry.getKey();
5807 14 Oct 11 nicklas 223         if (extracts.size() > 1 && positions.contains(tp.position))
5807 14 Oct 11 nicklas 224         {
5807 14 Oct 11 nicklas 225           // There are duplicates
5807 14 Oct 11 nicklas 226           Failure failure = context.createFailure(Validator.NONUNIQUE_TAG, parentNode, 
5807 14 Oct 11 nicklas 227             "Multiple extracts on position " + tp.position + " with tag: " + 
5807 14 Oct 11 nicklas 228             (tp.tag == null ? "none" : tp.tag.getName()));
5807 14 Oct 11 nicklas 229           if (failure != null)
5807 14 Oct 11 nicklas 230           {
5807 14 Oct 11 nicklas 231             failure.setDescriptor(tp);
5807 14 Oct 11 nicklas 232             failure.addFix(new Fix("Change extracts on physical bioassay", pba));
5807 14 Oct 11 nicklas 233             for (Extract e : extracts)
5807 14 Oct 11 nicklas 234             {
5807 14 Oct 11 nicklas 235               failure.addFix(new Fix("Change tag of '" + e.getName() + "'", e));
5807 14 Oct 11 nicklas 236             }
5807 14 Oct 11 nicklas 237           }
5807 14 Oct 11 nicklas 238         }
5807 14 Oct 11 nicklas 239       }
5807 14 Oct 11 nicklas 240     }
5807 14 Oct 11 nicklas 241     
5807 14 Oct 11 nicklas 242   }
4740 05 Feb 09 nicklas 243   // ----------------------------
5651 08 Jun 11 nicklas 244   
5651 08 Jun 11 nicklas 245   
5651 08 Jun 11 nicklas 246   /**
5651 08 Jun 11 nicklas 247     Check the subtype of the sample that is the parent to an extract. Given that
5651 08 Jun 11 nicklas 248     the extract has a non-null subtype, which has a related SAMPLE subtype, this
5651 08 Jun 11 nicklas 249     method checks if the parent sample has the same subtype. If there is no related
5651 08 Jun 11 nicklas 250     subtype for the extract, any subtype for the parent is accepted.
5651 08 Jun 11 nicklas 251     @since 3.0
5651 08 Jun 11 nicklas 252   */
5651 08 Jun 11 nicklas 253   public static void checkParentSampleSubtype(DbControl dc, OverviewContext context, Node extractNode, Node sampleNode)
5651 08 Jun 11 nicklas 254   {
5807 14 Oct 11 nicklas 255     Extract extract = (Extract)extractNode.getItem(dc);
5807 14 Oct 11 nicklas 256     Sample sample = (Sample)sampleNode.getItem(dc);
5651 08 Jun 11 nicklas 257     
5651 08 Jun 11 nicklas 258     try
5651 08 Jun 11 nicklas 259     {
5651 08 Jun 11 nicklas 260       ItemSubtype expectedSubtype = ItemSubtype.getRelatedSubtype(dc, extract, Item.SAMPLE, Item.EXTRACT);
5651 08 Jun 11 nicklas 261       ItemSubtype subtype = sample.getItemSubtype();
5651 08 Jun 11 nicklas 262       
5651 08 Jun 11 nicklas 263       if (expectedSubtype != null && !expectedSubtype.equals(subtype))
5651 08 Jun 11 nicklas 264       {
5807 14 Oct 11 nicklas 265         ItemSubtype mySubtype = extract.getItemSubtype();
5807 14 Oct 11 nicklas 266         Fix subtypeFix = subtype == null ? null : 
5807 14 Oct 11 nicklas 267           new Fix("Change related sample subtype of '" + mySubtype.getName() + 
5807 14 Oct 11 nicklas 268             "' to '" + subtype.getName() + "'", mySubtype);
5651 08 Jun 11 nicklas 269         if (expectedSubtype.getMainItemType() == Item.SAMPLE)
5651 08 Jun 11 nicklas 270         {
5651 08 Jun 11 nicklas 271           context.createFailure(Validator.INCORRECT_SAMPLE_TYPE, extractNode, 
5807 14 Oct 11 nicklas 272             "Expected a sample with subtype: " + expectedSubtype.getName(),
5807 14 Oct 11 nicklas 273             new Fix("Change subtype of '" + sample.getName() + "' to '" + expectedSubtype.getName() + "'", sample),
5807 14 Oct 11 nicklas 274             new Fix("Change subtype or parent sample of '" + extractNode.getTitle() + "'", extract),
5807 14 Oct 11 nicklas 275             subtypeFix
5651 08 Jun 11 nicklas 276           );
5651 08 Jun 11 nicklas 277         }
5651 08 Jun 11 nicklas 278         else
5651 08 Jun 11 nicklas 279         {
5651 08 Jun 11 nicklas 280           context.createFailure(Validator.INCORRECT_SAMPLE_TYPE, extractNode, 
5807 14 Oct 11 nicklas 281             "Expected an extract with subtype: " + expectedSubtype.getName(),
5807 14 Oct 11 nicklas 282             new Fix("Change subtype or parent of '" + extractNode.getTitle() + "'", extract),
5807 14 Oct 11 nicklas 283             subtypeFix
5651 08 Jun 11 nicklas 284           );
5651 08 Jun 11 nicklas 285         }
5651 08 Jun 11 nicklas 286       }
5651 08 Jun 11 nicklas 287     }
5651 08 Jun 11 nicklas 288     catch (PermissionDeniedException ex)
5651 08 Jun 11 nicklas 289     {}
5651 08 Jun 11 nicklas 290   }
5651 08 Jun 11 nicklas 291
5651 08 Jun 11 nicklas 292   /**
5651 08 Jun 11 nicklas 293     Check the subtype of the extract that is the parent to another extract. Given that
5651 08 Jun 11 nicklas 294     the child extract has a non-null subtype, which has a related EXTRACT subtype, this
5651 08 Jun 11 nicklas 295     method checks if the parent extract has the same subtype. If there is no related
5651 08 Jun 11 nicklas 296     subtype for the child extract, any subtype for the parent is accepted.
5651 08 Jun 11 nicklas 297     @since 3.0
5651 08 Jun 11 nicklas 298   */
5651 08 Jun 11 nicklas 299   public static void checkParentExtractSubtype(DbControl dc, OverviewContext context, Node childNode, Node parentNode)
5651 08 Jun 11 nicklas 300   {
5807 14 Oct 11 nicklas 301     Extract child = (Extract)childNode.getItem(dc);
5807 14 Oct 11 nicklas 302     Extract parent = (Extract)parentNode.getItem(dc);
5651 08 Jun 11 nicklas 303     
5651 08 Jun 11 nicklas 304     try
5651 08 Jun 11 nicklas 305     {
5807 14 Oct 11 nicklas 306       ItemSubtype expectedSubtype = ItemSubtype.getRelatedSubtype(dc, child, Item.EXTRACT, Item.SAMPLE);
5651 08 Jun 11 nicklas 307       ItemSubtype subtype = parent.getItemSubtype();
5651 08 Jun 11 nicklas 308       
5651 08 Jun 11 nicklas 309       if (expectedSubtype != null && !expectedSubtype.equals(subtype))
5651 08 Jun 11 nicklas 310       {
5807 14 Oct 11 nicklas 311         ItemSubtype mySubtype = child.getItemSubtype();
5807 14 Oct 11 nicklas 312         Fix subtypeFix = subtype == null || subtype.equals(mySubtype) ? null : 
5807 14 Oct 11 nicklas 313           new Fix("Change related extract subtype of '" + mySubtype.getName() + 
5807 14 Oct 11 nicklas 314             "' to '" + subtype.getName() + "'", mySubtype);
5807 14 Oct 11 nicklas 315         if (expectedSubtype.getMainItemType() == Item.EXTRACT)
5807 14 Oct 11 nicklas 316         {
5807 14 Oct 11 nicklas 317           context.createFailure(Validator.INCORRECT_EXTRACT_TYPE, childNode, 
5807 14 Oct 11 nicklas 318             "Expected an extract with subtype: " + expectedSubtype.getName(),
5807 14 Oct 11 nicklas 319             new Fix("Change subtype of '" + parent.getName() + "' to '" + expectedSubtype.getName() + "'", parent),
5807 14 Oct 11 nicklas 320             new Fix("Change subtype or parent extract of '" + childNode.getTitle() + "'", child),
5807 14 Oct 11 nicklas 321             subtypeFix
5807 14 Oct 11 nicklas 322           );
5807 14 Oct 11 nicklas 323         }
5807 14 Oct 11 nicklas 324         else
5807 14 Oct 11 nicklas 325         {
5807 14 Oct 11 nicklas 326           context.createFailure(Validator.INCORRECT_EXTRACT_TYPE, childNode, 
5807 14 Oct 11 nicklas 327             "Expected a sample with subtype: " + expectedSubtype.getName(),
5807 14 Oct 11 nicklas 328             new Fix("Change subtype or parent of '" + childNode.getTitle() + "'", child),
5807 14 Oct 11 nicklas 329             subtypeFix
5807 14 Oct 11 nicklas 330           );
5807 14 Oct 11 nicklas 331           
5807 14 Oct 11 nicklas 332         }
5651 08 Jun 11 nicklas 333       }
5651 08 Jun 11 nicklas 334     }
5651 08 Jun 11 nicklas 335     catch (PermissionDeniedException ex)
5651 08 Jun 11 nicklas 336     {}
5651 08 Jun 11 nicklas 337   }
5651 08 Jun 11 nicklas 338
5807 14 Oct 11 nicklas 339   /**
5807 14 Oct 11 nicklas 340     Check the tag of the child extract in relation to a parent extract. If the parent
5807 14 Oct 11 nicklas 341     extract has a tag, the child must have the same tag. If the parent is not
5807 14 Oct 11 nicklas 342     tagged, then the child may have any tag or no tag.
5807 14 Oct 11 nicklas 343     @since 3.0
5807 14 Oct 11 nicklas 344   */
5807 14 Oct 11 nicklas 345   public static void checkExtractTag(DbControl dc, OverviewContext context, Node childNode, Node parentNode)
5807 14 Oct 11 nicklas 346   {
5807 14 Oct 11 nicklas 347     Extract child = (Extract)childNode.getItem(dc);
5807 14 Oct 11 nicklas 348     Extract parent = (Extract)parentNode.getItem(dc);
5807 14 Oct 11 nicklas 349     
5807 14 Oct 11 nicklas 350     try
5807 14 Oct 11 nicklas 351     {
5807 14 Oct 11 nicklas 352       Tag parentTag = parent.getTag();
5807 14 Oct 11 nicklas 353       if (parentTag != null)
5807 14 Oct 11 nicklas 354       {
5807 14 Oct 11 nicklas 355         Tag childTag = child.getTag();
5807 14 Oct 11 nicklas 356         if (!parentTag.equals(childTag))
5807 14 Oct 11 nicklas 357         {
5807 14 Oct 11 nicklas 358           if (childTag != null)
5807 14 Oct 11 nicklas 359           {
5807 14 Oct 11 nicklas 360             context.createFailure(Validator.DIFFERENT_TAG, childNode,
5807 14 Oct 11 nicklas 361               "Extract '" + child.getName() + "' has tag mismatch: " + childTag.getName(),
5807 14 Oct 11 nicklas 362               new Fix("Change tag of '" + child.getName() + "' to '" + parentTag.getName() + "'", child),
5807 14 Oct 11 nicklas 363               new Fix("Change tag of '" + parent.getName() + "' to '" + childTag.getName() + "'", parent)
5807 14 Oct 11 nicklas 364             );
5807 14 Oct 11 nicklas 365           }
5807 14 Oct 11 nicklas 366           else
5807 14 Oct 11 nicklas 367           {
5807 14 Oct 11 nicklas 368             context.createFailure(Validator.TAGGED_PARENT, childNode,
5807 14 Oct 11 nicklas 369               "Extract '" + child.getName() + "' has no tag but parent has",
5807 14 Oct 11 nicklas 370               new Fix("Change tag of '" + child.getName() + "' to '" + parentTag.getName() + "'", child),
5807 14 Oct 11 nicklas 371               new Fix("Remove tag from '" + parent.getName() + "'", parent)
5807 14 Oct 11 nicklas 372             );
5807 14 Oct 11 nicklas 373           }
5807 14 Oct 11 nicklas 374           
5807 14 Oct 11 nicklas 375         }
5807 14 Oct 11 nicklas 376       }
5807 14 Oct 11 nicklas 377     }
5807 14 Oct 11 nicklas 378     catch (PermissionDeniedException ex)
5807 14 Oct 11 nicklas 379     {}
5807 14 Oct 11 nicklas 380   }
5807 14 Oct 11 nicklas 381
6098 03 Sep 12 nicklas 382   /**
6098 03 Sep 12 nicklas 383     Check if two given extracts have a parent-child relationship.
6098 03 Sep 12 nicklas 384     @since 3.2
6098 03 Sep 12 nicklas 385   */
6098 03 Sep 12 nicklas 386   @SuppressWarnings("unchecked")
6098 03 Sep 12 nicklas 387   public static boolean isRelated(DbControl dc, OverviewContext context, Extract parent, Extract child)
6098 03 Sep 12 nicklas 388   {
6100 04 Sep 12 nicklas 389     // Short-cut if both extracts are the same
6100 04 Sep 12 nicklas 390     if (child.equals(parent)) return true;
6100 04 Sep 12 nicklas 391     
6098 03 Sep 12 nicklas 392     String cacheKey = "extract." + child.getId() + ".parents";
6799 25 Mar 15 nicklas 393     Set<Integer> allParents = (Set<Integer>)context.getCachedObject(cacheKey);
6098 03 Sep 12 nicklas 394     
6098 03 Sep 12 nicklas 395     if (allParents == null)
6098 03 Sep 12 nicklas 396     {
6098 03 Sep 12 nicklas 397       if (child.getParentType() == Item.EXTRACT)
6098 03 Sep 12 nicklas 398       {
7605 26 Feb 19 nicklas 399         ItemQuery<Extract> query = child.getCreationEvent().getSources();
6098 03 Sep 12 nicklas 400         query.include(Include.ALL);
6799 25 Mar 15 nicklas 401         SourceItemTransformer transformer = new ExtractToParentExtractTransformer(true);
6799 25 Mar 15 nicklas 402         allParents = transformer.transform(new TransformContext(dc), new HashSet<Integer>(query.idList(dc)));
6098 03 Sep 12 nicklas 403       }
6098 03 Sep 12 nicklas 404       else
6098 03 Sep 12 nicklas 405       {
6098 03 Sep 12 nicklas 406         allParents = Collections.emptySet();
6098 03 Sep 12 nicklas 407       }
6098 03 Sep 12 nicklas 408       context.setCachedObject(cacheKey, allParents);
6098 03 Sep 12 nicklas 409     }
6799 25 Mar 15 nicklas 410     return allParents.contains(parent.getId());
6098 03 Sep 12 nicklas 411   }
5807 14 Oct 11 nicklas 412
5807 14 Oct 11 nicklas 413   private void checkExtractOnBioAssay(DbControl dc, OverviewContext context, Node extractNode, Node bioAssayNode)
5807 14 Oct 11 nicklas 414   {
5807 14 Oct 11 nicklas 415     // Check that the extract's position is within the expected range
5807 14 Oct 11 nicklas 416     PhysicalBioAssay bioAssay = (PhysicalBioAssay)bioAssayNode.getItem(dc);
5807 14 Oct 11 nicklas 417     int bioAssaySize = bioAssay.getSize();
5807 14 Oct 11 nicklas 418     Extract extract = (Extract)extractNode.getItem(dc);
5807 14 Oct 11 nicklas 419     BioMaterialEventSource src = bioAssay.getCreationEvent().getEventSource(extract);
5807 14 Oct 11 nicklas 420     int position = src.getPosition();
5807 14 Oct 11 nicklas 421     if (position > bioAssaySize || position < 1)
5807 14 Oct 11 nicklas 422     {
5813 18 Oct 11 nicklas 423       context.createFailure(Validator.INCORRECT_BIOASSAY_POSITION, bioAssayNode,
5813 18 Oct 11 nicklas 424           "Incorrect position for '" + extract.getName() + "': " + 
5813 18 Oct 11 nicklas 425             position + " (expected 1.." + bioAssaySize + ")",
5813 18 Oct 11 nicklas 426           new Fix("Change position for extract: " + extract.getName(), bioAssay), 
5807 14 Oct 11 nicklas 427           position <= 0 ? null : new Fix("Increase size of physical bioassay", bioAssay));
5807 14 Oct 11 nicklas 428     }
5807 14 Oct 11 nicklas 429   }
5651 08 Jun 11 nicklas 430   
5807 14 Oct 11 nicklas 431   
5807 14 Oct 11 nicklas 432   static class TagPosition
5807 14 Oct 11 nicklas 433   {
5807 14 Oct 11 nicklas 434     final Tag tag;
5807 14 Oct 11 nicklas 435     final int position;
5807 14 Oct 11 nicklas 436     
5807 14 Oct 11 nicklas 437     TagPosition(Tag tag, int position)
5807 14 Oct 11 nicklas 438     {
5807 14 Oct 11 nicklas 439       this.tag = tag;
5807 14 Oct 11 nicklas 440       this.position = position;
5807 14 Oct 11 nicklas 441     }
5807 14 Oct 11 nicklas 442     
5807 14 Oct 11 nicklas 443     @Override
5807 14 Oct 11 nicklas 444     public int hashCode()
5807 14 Oct 11 nicklas 445     {
5807 14 Oct 11 nicklas 446       return EqualsHelper.hashCode(tag) + position;
5807 14 Oct 11 nicklas 447     }
5807 14 Oct 11 nicklas 448     
5807 14 Oct 11 nicklas 449     @Override
5807 14 Oct 11 nicklas 450     public boolean equals(Object o)
5807 14 Oct 11 nicklas 451     {
5807 14 Oct 11 nicklas 452       TagPosition other = (TagPosition)o;
5807 14 Oct 11 nicklas 453       return EqualsHelper.equals(this.tag, other.tag) && this.position == other.position;
5807 14 Oct 11 nicklas 454     }
5807 14 Oct 11 nicklas 455     
5807 14 Oct 11 nicklas 456   }
5807 14 Oct 11 nicklas 457   
4740 05 Feb 09 nicklas 458 }