extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/dao/SpecimenTube.java

Code
Comments
Other
Rev Date Author Line
1326 29 Mar 11 nicklas 1 package net.sf.basedb.reggie.dao;
1326 29 Mar 11 nicklas 2
1326 29 Mar 11 nicklas 3 import java.util.ArrayList;
3779 10 Mar 16 nicklas 4 import java.util.Collection;
2840 20 Oct 14 nicklas 5 import java.util.HashMap;
1326 29 Mar 11 nicklas 6 import java.util.List;
2840 20 Oct 14 nicklas 7 import java.util.Map;
1326 29 Mar 11 nicklas 8
4482 05 May 17 nicklas 9 import net.sf.basedb.core.AnnotationRestriction;
3247 14 Apr 15 nicklas 10 import net.sf.basedb.core.AnnotationSimpleRestriction;
4964 03 Sep 18 nicklas 11 import net.sf.basedb.core.AnnotationType;
1379 27 Jun 11 martin 12 import net.sf.basedb.core.BioWell;
1326 29 Mar 11 nicklas 13 import net.sf.basedb.core.DbControl;
3146 25 Feb 15 nicklas 14 import net.sf.basedb.core.Extract;
1326 29 Mar 11 nicklas 15 import net.sf.basedb.core.Include;
1372 23 May 11 martin 16 import net.sf.basedb.core.InvalidDataException;
1326 29 Mar 11 nicklas 17 import net.sf.basedb.core.ItemQuery;
1492 02 Dec 11 nicklas 18 import net.sf.basedb.core.MeasuredBioMaterial;
3247 14 Apr 15 nicklas 19 import net.sf.basedb.core.Operator;
1326 29 Mar 11 nicklas 20 import net.sf.basedb.core.Sample;
1326 29 Mar 11 nicklas 21 import net.sf.basedb.core.Type;
1623 26 Apr 12 nicklas 22 import net.sf.basedb.core.query.Annotations;
1326 29 Mar 11 nicklas 23 import net.sf.basedb.core.query.Expressions;
1326 29 Mar 11 nicklas 24 import net.sf.basedb.core.query.Hql;
1326 29 Mar 11 nicklas 25 import net.sf.basedb.core.query.Orders;
3145 25 Feb 15 nicklas 26 import net.sf.basedb.core.query.Restriction;
1326 29 Mar 11 nicklas 27 import net.sf.basedb.core.query.Restrictions;
1826 07 Feb 13 nicklas 28 import net.sf.basedb.reggie.JsonUtil;
1678 31 May 12 nicklas 29 import net.sf.basedb.reggie.Reggie;
1326 29 Mar 11 nicklas 30
1406 17 Oct 11 martin 31 import org.json.simple.JSONObject;
1406 17 Oct 11 martin 32
1326 29 Mar 11 nicklas 33 /**
1326 29 Mar 11 nicklas 34   Class for loading information that is related to specimen tubes.
1326 29 Mar 11 nicklas 35   
1326 29 Mar 11 nicklas 36   @author nicklas
1326 29 Mar 11 nicklas 37   @since 1.2
1326 29 Mar 11 nicklas 38 */
1326 29 Mar 11 nicklas 39 public class SpecimenTube 
1326 29 Mar 11 nicklas 40   extends ReggieItem<Sample>
1326 29 Mar 11 nicklas 41 {
1326 29 Mar 11 nicklas 42
7186 22 May 23 nicklas 43   /**
7186 22 May 23 nicklas 44     @since 4.47
7186 22 May 23 nicklas 45   */
7186 22 May 23 nicklas 46   public static final String FLAG_MISSING_IN_TRANSPORT_BOX = "MissingInTransportBox";
7186 22 May 23 nicklas 47   
2840 20 Oct 14 nicklas 48   public static final Map<String, String> suffix2BiopsyType = new HashMap<String, String>();
2840 20 Oct 14 nicklas 49   
2840 20 Oct 14 nicklas 50   static
2840 20 Oct 14 nicklas 51   {
2840 20 Oct 14 nicklas 52     suffix2BiopsyType.put("C", "SpecimenCoreBiopsy");
2840 20 Oct 14 nicklas 53     suffix2BiopsyType.put("D", "SpecimenCoreBiopsy2nd");
2840 20 Oct 14 nicklas 54   }
2840 20 Oct 14 nicklas 55   
1326 29 Mar 11 nicklas 56   /**
1326 29 Mar 11 nicklas 57     Find all specimen tubes associated with a given case. This method can either
1326 29 Mar 11 nicklas 58     load all (including merged) specimen tubes, or only specimen tubes that
1326 29 Mar 11 nicklas 59     are really part of the original case.
1623 26 Apr 12 nicklas 60     <p>
1623 26 Apr 12 nicklas 61     If useBiopsyTypeAnnotation is set the lookup will use the 'BiopsyType' annotation
2840 20 Oct 14 nicklas 62     when searching for samples. If the case name has a C or D suffix only samples annotated 
2840 20 Oct 14 nicklas 63     with BiopsyType=SpecimenCoreBiopsy/SpecimenCoreBiopsy2nd are considered. If no suffix is 
2840 20 Oct 14 nicklas 64     specified SpecimenCoreBiopsy* samples are ignored.
1326 29 Mar 11 nicklas 65   */
1623 26 Apr 12 nicklas 66   public static List<SpecimenTube> findByCase(DbControl dc, Case theCase, String originalCaseName, boolean useBiopsyTypeAnnotation)
1326 29 Mar 11 nicklas 67   {
1326 29 Mar 11 nicklas 68     ItemQuery<Sample> specimenQuery = theCase.getSample().getChildSamples();
1503 18 Jan 12 nicklas 69     Subtype.SPECIMEN.addFilter(dc, specimenQuery);
1623 26 Apr 12 nicklas 70     if (originalCaseName != null)
1326 29 Mar 11 nicklas 71     {
2840 20 Oct 14 nicklas 72       String suffix = null;
2840 20 Oct 14 nicklas 73       if (originalCaseName.length() > 7) 
2840 20 Oct 14 nicklas 74       {
2840 20 Oct 14 nicklas 75         suffix = originalCaseName.substring(7, 8);
2840 20 Oct 14 nicklas 76         originalCaseName = originalCaseName.substring(0, 7);
2840 20 Oct 14 nicklas 77       }
1623 26 Apr 12 nicklas 78       specimenQuery.restrict(Restrictions.like(Hql.property("name"), Expressions.parameter("name", originalCaseName + ".%", Type.STRING)));
1623 26 Apr 12 nicklas 79       if (useBiopsyTypeAnnotation)
1623 26 Apr 12 nicklas 80       {
2840 20 Oct 14 nicklas 81         SpecimenTube.addBiopsyTypeFilter(dc, specimenQuery, suffix);
1623 26 Apr 12 nicklas 82       }
1326 29 Mar 11 nicklas 83     }
1326 29 Mar 11 nicklas 84     specimenQuery.order(Orders.asc(Hql.property("name")));
1326 29 Mar 11 nicklas 85     specimenQuery.include(Include.ALL);
1326 29 Mar 11 nicklas 86     List<SpecimenTube> tubes = new ArrayList<SpecimenTube>();
1326 29 Mar 11 nicklas 87     for (Sample s : specimenQuery.list(dc))
1326 29 Mar 11 nicklas 88     {
1326 29 Mar 11 nicklas 89       tubes.add(new SpecimenTube(s));
1326 29 Mar 11 nicklas 90     }
1326 29 Mar 11 nicklas 91     return tubes;
1326 29 Mar 11 nicklas 92   }
1326 29 Mar 11 nicklas 93   
1326 29 Mar 11 nicklas 94   /**
1326 29 Mar 11 nicklas 95     Find all specimen tubes that are linked by name to a given case name. The assumption
1326 29 Mar 11 nicklas 96     is that the case has not yet been registered and we are trying to find all specimen
1326 29 Mar 11 nicklas 97     tubes that are associated with it. The specimen tubes start with the same name as the
1326 29 Mar 11 nicklas 98     case and then have a suffix with a dot plus a running number. Eg. xxx.1, xxx.2, etc.
1623 26 Apr 12 nicklas 99     <p>
1623 26 Apr 12 nicklas 100     If useBiopsyTypeAnnotation is set the lookup will use the 'BiopsyType' annotation
1623 26 Apr 12 nicklas 101     when searching for samples. If the case name has a suffix 'C' only samples annotated 
1623 26 Apr 12 nicklas 102     with BiopsyType=SpecimenCoreBiopsy are considered. If no suffix is specified SpecimenCoreBiopsy
1623 26 Apr 12 nicklas 103     samples are ignored.
1326 29 Mar 11 nicklas 104   */
1623 26 Apr 12 nicklas 105   public static List<SpecimenTube> findByCaseName(DbControl dc, String name, boolean useBiopsyTypeAnnotation)
1326 29 Mar 11 nicklas 106   {
2840 20 Oct 14 nicklas 107     String suffix = null;
2840 20 Oct 14 nicklas 108     if (name.length() > 7) 
2840 20 Oct 14 nicklas 109     {
2840 20 Oct 14 nicklas 110       suffix = name.substring(7, 8);
2840 20 Oct 14 nicklas 111       name = name.substring(0, 7);
2840 20 Oct 14 nicklas 112     }
1623 26 Apr 12 nicklas 113     
1326 29 Mar 11 nicklas 114     ItemQuery<Sample> specimenQuery = Sample.getQuery();
1503 18 Jan 12 nicklas 115     Subtype.SPECIMEN.addFilter(dc, specimenQuery);
1492 02 Dec 11 nicklas 116     specimenQuery.restrict(Restrictions.like(Hql.property("name"), Expressions.parameter("name", name + ".%", Type.STRING)));
1326 29 Mar 11 nicklas 117     specimenQuery.order(Orders.asc(Hql.property("name")));
2917 11 Nov 14 nicklas 118     specimenQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1326 29 Mar 11 nicklas 119     
1623 26 Apr 12 nicklas 120     if (useBiopsyTypeAnnotation)
1623 26 Apr 12 nicklas 121     {
2840 20 Oct 14 nicklas 122       SpecimenTube.addBiopsyTypeFilter(dc, specimenQuery, suffix);
1623 26 Apr 12 nicklas 123     }
1623 26 Apr 12 nicklas 124     
1326 29 Mar 11 nicklas 125     List<SpecimenTube> tubes = new ArrayList<SpecimenTube>();
1326 29 Mar 11 nicklas 126     for (Sample s : specimenQuery.list(dc))
1379 27 Jun 11 martin 127     {    
1326 29 Mar 11 nicklas 128       tubes.add(new SpecimenTube(s));
1326 29 Mar 11 nicklas 129     }
1326 29 Mar 11 nicklas 130     return tubes;
1326 29 Mar 11 nicklas 131   }
1326 29 Mar 11 nicklas 132   
1492 02 Dec 11 nicklas 133   /**
1492 02 Dec 11 nicklas 134      Find a specimen tube with the given name.
1492 02 Dec 11 nicklas 135      @return A specimen tube, or null if not found
1492 02 Dec 11 nicklas 136   */
1372 23 May 11 martin 137   public static SpecimenTube findByTubeName(DbControl dc, String tubeName)
1372 23 May 11 martin 138   {
1372 23 May 11 martin 139     SpecimenTube tube = null;
1372 23 May 11 martin 140     
1372 23 May 11 martin 141     ItemQuery<Sample> tubeQuery = Sample.getQuery();
1503 18 Jan 12 nicklas 142     Subtype.SPECIMEN.addFilter(dc, tubeQuery);
1372 23 May 11 martin 143     tubeQuery.restrict(Restrictions.like(Hql.property("name"), Expressions.string(tubeName)));
4031 26 Jul 16 nicklas 144     tubeQuery.order(Orders.desc(Hql.property("name")));
4031 26 Jul 16 nicklas 145     tubeQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1372 23 May 11 martin 146     
1372 23 May 11 martin 147     List<Sample> tubes = tubeQuery.list(dc);
1372 23 May 11 martin 148     if (tubes.size() > 1)
1372 23 May 11 martin 149     {
1372 23 May 11 martin 150       throw new InvalidDataException(
1372 23 May 11 martin 151           "More than one specimen tube with the name " + tubeName + " was found. " +
1372 23 May 11 martin 152           "This wizard can't be used until that is corrected.");
1372 23 May 11 martin 153     }
1372 23 May 11 martin 154     if (tubes.size() == 1)
1372 23 May 11 martin 155     {
1372 23 May 11 martin 156       tube = new SpecimenTube(tubes.get(0));
1372 23 May 11 martin 157     }
1372 23 May 11 martin 158     return tube;
1372 23 May 11 martin 159   }
1372 23 May 11 martin 160   
1419 28 Oct 11 martin 161   /**
4075 05 Sep 16 nicklas 162      Find a specimen tube with the given external ID.
4075 05 Sep 16 nicklas 163      @return A specimen tube, or null if not found
4075 05 Sep 16 nicklas 164      @since 4.7
4075 05 Sep 16 nicklas 165   */
4075 05 Sep 16 nicklas 166   public static SpecimenTube findByExternalId(DbControl dc, String externalId)
4075 05 Sep 16 nicklas 167   {
4075 05 Sep 16 nicklas 168     SpecimenTube tube = null;
4075 05 Sep 16 nicklas 169     
4075 05 Sep 16 nicklas 170     ItemQuery<Sample> tubeQuery = Sample.getQuery();
4075 05 Sep 16 nicklas 171     Subtype.SPECIMEN.addFilter(dc, tubeQuery);
4075 05 Sep 16 nicklas 172     tubeQuery.restrict(Restrictions.eq(Hql.property("externalId"), Expressions.string(externalId)));
4075 05 Sep 16 nicklas 173     tubeQuery.order(Orders.desc(Hql.property("name")));
4075 05 Sep 16 nicklas 174     tubeQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
4075 05 Sep 16 nicklas 175     
4075 05 Sep 16 nicklas 176     List<Sample> tubes = tubeQuery.list(dc);
4075 05 Sep 16 nicklas 177     if (tubes.size() > 1)
4075 05 Sep 16 nicklas 178     {
4075 05 Sep 16 nicklas 179       throw new InvalidDataException(
4075 05 Sep 16 nicklas 180           "More than one specimen tube with the external id '" + externalId + "' was found. " +
4075 05 Sep 16 nicklas 181           "This wizard can't be used until that is corrected.");
4075 05 Sep 16 nicklas 182     }
4075 05 Sep 16 nicklas 183     if (tubes.size() == 1)
4075 05 Sep 16 nicklas 184     {
4075 05 Sep 16 nicklas 185       tube = new SpecimenTube(tubes.get(0));
4075 05 Sep 16 nicklas 186     }
4075 05 Sep 16 nicklas 187     return tube;
4075 05 Sep 16 nicklas 188   }
4075 05 Sep 16 nicklas 189   
4075 05 Sep 16 nicklas 190   /**
4964 03 Sep 18 nicklas 191     Find a specimen tubes by PAD. Not that multiple tubes
4964 03 Sep 18 nicklas 192     may be registered with the same PAD. Note that if the logged
4964 03 Sep 18 nicklas 193     in user doesn't have permission to access PAD information
4964 03 Sep 18 nicklas 194     this method will throw a PermissionDeniedException.
4964 03 Sep 18 nicklas 195     
4964 03 Sep 18 nicklas 196     @param dc DbControl The DbControl to use.
4964 03 Sep 18 nicklas 197     @param pad The PAD to look for
4964 03 Sep 18 nicklas 198     @since 4.19.1
4964 03 Sep 18 nicklas 199   */
4964 03 Sep 18 nicklas 200   public static List<SpecimenTube> findByPAD(DbControl dc, String pad)
4964 03 Sep 18 nicklas 201   {
4964 03 Sep 18 nicklas 202     AnnotationType padType = Annotationtype.PAD.load(dc);
4964 03 Sep 18 nicklas 203
4964 03 Sep 18 nicklas 204     ItemQuery<Sample> tubeQuery = Sample.getQuery();
4964 03 Sep 18 nicklas 205     Subtype.SPECIMEN.addFilter(dc, tubeQuery);
4964 03 Sep 18 nicklas 206     tubeQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
4964 03 Sep 18 nicklas 207     tubeQuery.restrict(new AnnotationSimpleRestriction(null, padType, Operator.EQ, pad, new AnnotationRestriction.Options()));
4964 03 Sep 18 nicklas 208     List<Sample> tubes = tubeQuery.list(dc);
4964 03 Sep 18 nicklas 209     
4964 03 Sep 18 nicklas 210     return toList(tubes);
4964 03 Sep 18 nicklas 211   }
4964 03 Sep 18 nicklas 212
7150 09 May 23 nicklas 213   /**
7150 09 May 23 nicklas 214     Find a specimen tubes by ExternalRef. Typically only
7150 09 May 23 nicklas 215     a single specimen should be registered with the same ExternalRef,
7150 09 May 23 nicklas 216     but we return a list that may have more hits and delegate the
7150 09 May 23 nicklas 217     calling to code to handle multiple hits.
7150 09 May 23 nicklas 218     
7150 09 May 23 nicklas 219     @param dc DbControl The DbControl to use.
7150 09 May 23 nicklas 220     @param ref The ExternalRef to look for
7150 09 May 23 nicklas 221     @since 4.47
7150 09 May 23 nicklas 222   */
7150 09 May 23 nicklas 223   public static List<SpecimenTube> findByExternalRef(DbControl dc, String ref)
7150 09 May 23 nicklas 224   {
7150 09 May 23 nicklas 225     AnnotationType eRefType = Annotationtype.EXTERNAL_REF.load(dc);
4964 03 Sep 18 nicklas 226   
7150 09 May 23 nicklas 227     ItemQuery<Sample> tubeQuery = Sample.getQuery();
7150 09 May 23 nicklas 228     Subtype.SPECIMEN.addFilter(dc, tubeQuery);
7150 09 May 23 nicklas 229     tubeQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
7150 09 May 23 nicklas 230     tubeQuery.restrict(new AnnotationSimpleRestriction(null, eRefType, Operator.LIKE, "%"+ref, new AnnotationRestriction.Options()));
7150 09 May 23 nicklas 231     List<Sample> tubes = tubeQuery.list(dc);
7150 09 May 23 nicklas 232     
7150 09 May 23 nicklas 233     return toList(tubes);
7150 09 May 23 nicklas 234   }
7150 09 May 23 nicklas 235
4964 03 Sep 18 nicklas 236   /**
1492 02 Dec 11 nicklas 237     Find unpartitioned specimen tubes. A specimen tube that has not been partitioned
1492 02 Dec 11 nicklas 238     have a 'null' {@link MeasuredBioMaterial#getOriginalQuantity()}.
1419 28 Oct 11 martin 239      @since 1.6
1492 02 Dec 11 nicklas 240   */
3145 25 Feb 15 nicklas 241   public static List<SpecimenTube> findUnPartitionedTubes(DbControl dc, boolean includeReProcess)
1419 28 Oct 11 martin 242   {
1419 28 Oct 11 martin 243     List<SpecimenTube> unPartitionedTubes = new ArrayList<SpecimenTube>();
1419 28 Oct 11 martin 244     
1419 28 Oct 11 martin 245     ItemQuery<Sample> tubeQuery = Sample.getQuery();
3145 25 Feb 15 nicklas 246     tubeQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
1503 18 Jan 12 nicklas 247     Subtype.SPECIMEN.addFilter(dc, tubeQuery);
3145 25 Feb 15 nicklas 248     // Default criteria is to only include items with originalQuantity=null
3145 25 Feb 15 nicklas 249     Restriction criteria = Restrictions.eq(Hql.property("originalQuantity"), null);
3145 25 Feb 15 nicklas 250     
3145 25 Feb 15 nicklas 251     if (includeReProcess)
3145 25 Feb 15 nicklas 252     {
3145 25 Feb 15 nicklas 253       tubeQuery.join(Annotations.leftJoin(null, Annotationtype.AUTO_PROCESSING.load(dc), "ap"));
3145 25 Feb 15 nicklas 254       // Also include items with AutoProcessing=ReProcess
3145 25 Feb 15 nicklas 255       criteria = Restrictions.or(
3145 25 Feb 15 nicklas 256         criteria,
3145 25 Feb 15 nicklas 257         Restrictions.eq(Hql.alias("ap"), Expressions.string("ReProcess"))
3145 25 Feb 15 nicklas 258       );
3145 25 Feb 15 nicklas 259     }
3145 25 Feb 15 nicklas 260     tubeQuery.restrict(criteria);
3145 25 Feb 15 nicklas 261     
1449 02 Nov 11 martin 262     tubeQuery.order(Orders.desc(Hql.property("id")));
1419 28 Oct 11 martin 263     List<Sample> tubes = tubeQuery.list(dc);
1419 28 Oct 11 martin 264     for (Sample tube : tubes)
1419 28 Oct 11 martin 265     {
1456 09 Nov 11 martin 266       BioWell well = tube.getBioWell();
1456 09 Nov 11 martin 267       String boxNamePrefix = null;
1503 18 Jan 12 nicklas 268
3145 25 Feb 15 nicklas 269       String autoProcessing = (String)Annotationtype.AUTO_PROCESSING.getAnnotationValue(dc, tube);
1456 09 Nov 11 martin 270       if (well != null)
1449 02 Nov 11 martin 271       {
1456 09 Nov 11 martin 272         boxNamePrefix = well.getPlate().getName().substring(0,2);        
1456 09 Nov 11 martin 273       }
3145 25 Feb 15 nicklas 274       if ("ReProcess".equals(autoProcessing) || (tube.countExtracts() == 0 && "Sp".equals(boxNamePrefix)))
1456 09 Nov 11 martin 275       {
1449 02 Nov 11 martin 276         unPartitionedTubes.add(new SpecimenTube(tube));
1449 02 Nov 11 martin 277       }
1419 28 Oct 11 martin 278     }
1419 28 Oct 11 martin 279     return unPartitionedTubes;
1419 28 Oct 11 martin 280   }
1419 28 Oct 11 martin 281   
4898 10 Jul 18 nicklas 282   
4898 10 Jul 18 nicklas 283   /**
4898 10 Jul 18 nicklas 284     Find the next name to give a "Specimen" or "NoSpecimen" item. This assumes that
4898 10 Jul 18 nicklas 285     all items are using the naming convention: foo.1, foo.2, and
4898 10 Jul 18 nicklas 286     so on.
4898 10 Jul 18 nicklas 287     @return The next unused name
4898 10 Jul 18 nicklas 288     @since 4.19
4898 10 Jul 18 nicklas 289   */
7000 20 Jan 23 nicklas 290   public static String getNextSpecimenName(DbControl dc, String caseName, boolean releaseIfTransactionFails)
4898 10 Jul 18 nicklas 291   {
4964 03 Sep 18 nicklas 292     if (caseName.length() > 7) 
4964 03 Sep 18 nicklas 293     {
4964 03 Sep 18 nicklas 294       caseName = caseName.substring(0, 7);
4964 03 Sep 18 nicklas 295     }
4964 03 Sep 18 nicklas 296
4898 10 Jul 18 nicklas 297     ItemQuery<Sample> query = Sample.getQuery();
4898 10 Jul 18 nicklas 298     query.setIncludes(Include.ALL);
4898 10 Jul 18 nicklas 299     query.restrict(Restrictions.or(
4898 10 Jul 18 nicklas 300         Subtype.SPECIMEN.restriction(dc, null), 
6510 03 Dec 21 nicklas 301         Subtype.NO_SPECIMEN.restriction(dc, null)
4898 10 Jul 18 nicklas 302         ));
4898 10 Jul 18 nicklas 303     query.restrict(Restrictions.like(Hql.property("name"), Expressions.string(caseName + ".%")));
7000 20 Jan 23 nicklas 304     return ReggieItem.getNextChildItemName(dc, caseName, query, "", releaseIfTransactionFails);
4898 10 Jul 18 nicklas 305   }
4898 10 Jul 18 nicklas 306
4071 02 Sep 16 nicklas 307   /**
4071 02 Sep 16 nicklas 308     Generate the next auto-generated external ID. This method will search all specimen/nospecimen
4071 02 Sep 16 nicklas 309     starting with the given prefix and find the one with the highest numeric suffix. 
4902 10 Jul 18 nicklas 310     The returned string is the found item + 1. 
4902 10 Jul 18 nicklas 311     @since 4.19
4071 02 Sep 16 nicklas 312   */
5088 13 Nov 18 nicklas 313   public static String getNextExternalId(DbControl dc, Subtype subtype)
4071 02 Sep 16 nicklas 314   {
4071 02 Sep 16 nicklas 315     ItemQuery<Sample> spQuery = Sample.getQuery();
5088 13 Nov 18 nicklas 316     return ReggieItem.getNextExternalId(dc, spQuery, subtype.getExternalIdPrefix());
4071 02 Sep 16 nicklas 317   }
4071 02 Sep 16 nicklas 318
4071 02 Sep 16 nicklas 319   
2840 20 Oct 14 nicklas 320   public static void addBiopsyTypeFilter(DbControl dc, ItemQuery<Sample> query, String suffix)
2840 20 Oct 14 nicklas 321   {
2840 20 Oct 14 nicklas 322     if (suffix != null)
2840 20 Oct 14 nicklas 323     {
2840 20 Oct 14 nicklas 324       // Only look for samples specific annotation BiopsyType (C=SpecimenCoreBiopsy, D=SpecimenCoreBiopsy2nd)
4482 05 May 17 nicklas 325       query.restrict(new AnnotationSimpleRestriction(null, Annotationtype.BIOPSY_TYPE.load(dc), Operator.EQ, suffix2BiopsyType.get(suffix), new AnnotationRestriction.Options()));
2840 20 Oct 14 nicklas 326     }
2840 20 Oct 14 nicklas 327     else
2840 20 Oct 14 nicklas 328     {
2840 20 Oct 14 nicklas 329       // Ignore samples with BiopsyType = any that require suffix
2840 20 Oct 14 nicklas 330       query.join(Annotations.leftJoin(Annotationtype.BIOPSY_TYPE.load(dc), "bt"));
2840 20 Oct 14 nicklas 331       query.restrict(
2840 20 Oct 14 nicklas 332         Restrictions.or(
2840 20 Oct 14 nicklas 333           Restrictions.not(Restrictions.in(Hql.alias("bt"), Expressions.parameter("btValues"))),
2840 20 Oct 14 nicklas 334           Restrictions.eq(Hql.alias("bt"), null)
2840 20 Oct 14 nicklas 335         ));
2840 20 Oct 14 nicklas 336       query.setParameter("btValues", suffix2BiopsyType.values(), Type.STRING);
2840 20 Oct 14 nicklas 337     }
2840 20 Oct 14 nicklas 338   }
3146 25 Feb 15 nicklas 339   
3146 25 Feb 15 nicklas 340   /**
5333 28 Mar 19 nicklas 341     Get the specimen that was the last one to be placed in a storage box with the
5333 28 Mar 19 nicklas 342     given prefix. Eg. 'Sp' for regular storage boxes or 'PSp' for paused storage
7140 28 Apr 23 nicklas 343     boxes. If a subtype is specified only consider items of the specified type.
7140 28 Apr 23 nicklas 344     @since 4.47
5333 28 Mar 19 nicklas 345   */
7140 28 Apr 23 nicklas 346   public static SpecimenTube getLastPlacedSpecimen(DbControl dc, Subtype subtype, String boxPrefix)
5333 28 Mar 19 nicklas 347   {
5333 28 Mar 19 nicklas 348     ItemQuery<Sample> spQuery = Sample.getQuery();
5333 28 Mar 19 nicklas 349     spQuery.setIncludes(Reggie.INCLUDE_IN_CURRENT_PROJECT);
7140 28 Apr 23 nicklas 350     if (subtype != null) subtype.addFilter(dc, spQuery);
5333 28 Mar 19 nicklas 351     spQuery.join(Hql.innerJoin("bioWell", "bw"));
5333 28 Mar 19 nicklas 352     spQuery.join(Hql.innerJoin("bw", "bioPlate", "bp"));
5333 28 Mar 19 nicklas 353     spQuery.restrict(Restrictions.like(Hql.property("bp", "name"), Expressions.string(boxPrefix+"%")));
5333 28 Mar 19 nicklas 354     spQuery.order(Orders.desc(Hql.property("bp", "name")));
5333 28 Mar 19 nicklas 355     spQuery.order(Orders.desc(Hql.property("bw", "row")));
5333 28 Mar 19 nicklas 356     spQuery.order(Orders.desc(Hql.property("bw", "column")));
5333 28 Mar 19 nicklas 357     spQuery.setMaxResults(1);
5333 28 Mar 19 nicklas 358     List<Sample> lastPlacedSpecimen = spQuery.list(dc);
5333 28 Mar 19 nicklas 359     return lastPlacedSpecimen.size() > 0 ? new SpecimenTube(lastPlacedSpecimen.get(0)) : null;
5333 28 Mar 19 nicklas 360   }
5333 28 Mar 19 nicklas 361   
5333 28 Mar 19 nicklas 362   /**
3146 25 Feb 15 nicklas 363     Get a Specimen item when the id is known.
3146 25 Feb 15 nicklas 364     @since 3.2
3146 25 Feb 15 nicklas 365   */
3146 25 Feb 15 nicklas 366   public static SpecimenTube getById(DbControl dc, int id)
3146 25 Feb 15 nicklas 367   {
3146 25 Feb 15 nicklas 368     return new SpecimenTube(Sample.getById(dc, id));
3146 25 Feb 15 nicklas 369   }
2840 20 Oct 14 nicklas 370
3166 05 Mar 15 nicklas 371   /**
3166 05 Mar 15 nicklas 372     @since 3.2
3166 05 Mar 15 nicklas 373   */
3166 05 Mar 15 nicklas 374   public static SpecimenTube get(Sample sample)
3166 05 Mar 15 nicklas 375   {
3166 05 Mar 15 nicklas 376     return new SpecimenTube(sample);
3166 05 Mar 15 nicklas 377   }
3166 05 Mar 15 nicklas 378
3779 10 Mar 16 nicklas 379   /**
3779 10 Mar 16 nicklas 380     @since 4.3
3779 10 Mar 16 nicklas 381   */
3779 10 Mar 16 nicklas 382   public static List<SpecimenTube> toList(Collection<Sample> samples)
3779 10 Mar 16 nicklas 383   {
3779 10 Mar 16 nicklas 384     List<SpecimenTube> tubes = new ArrayList<SpecimenTube>(samples.size());
3779 10 Mar 16 nicklas 385     for (Sample s : samples)
3779 10 Mar 16 nicklas 386     {
3779 10 Mar 16 nicklas 387       tubes.add(new SpecimenTube(s));
3779 10 Mar 16 nicklas 388     }
3779 10 Mar 16 nicklas 389     return tubes;
3779 10 Mar 16 nicklas 390   }
2840 20 Oct 14 nicklas 391   
1821 06 Feb 13 nicklas 392   private JSONObject jsonWell;
1379 27 Jun 11 martin 393   
1326 29 Mar 11 nicklas 394   private SpecimenTube(Sample sample)
1326 29 Mar 11 nicklas 395   {
1326 29 Mar 11 nicklas 396     super(sample);
1379 27 Jun 11 martin 397   }  
1326 29 Mar 11 nicklas 398   
1379 27 Jun 11 martin 399   
1326 29 Mar 11 nicklas 400   /**
1326 29 Mar 11 nicklas 401     Get the real sample that represents this speciment tube in BASE.
1326 29 Mar 11 nicklas 402   */
1326 29 Mar 11 nicklas 403   public Sample getSample()
1326 29 Mar 11 nicklas 404   {
1326 29 Mar 11 nicklas 405     return getItem();
1326 29 Mar 11 nicklas 406   }
1326 29 Mar 11 nicklas 407
1821 06 Feb 13 nicklas 408   @Override
1821 06 Feb 13 nicklas 409   protected void initJSON(JSONObject json)
1379 27 Jun 11 martin 410   {
1821 06 Feb 13 nicklas 411     super.initJSON(json);
1821 06 Feb 13 nicklas 412     if (jsonWell != null) json.put("bioWell", jsonWell);
1379 27 Jun 11 martin 413   }
1821 06 Feb 13 nicklas 414   
1379 27 Jun 11 martin 415   /**
1821 06 Feb 13 nicklas 416     Load information about the plate and location the current RNA
1821 06 Feb 13 nicklas 417     is located on.
1379 27 Jun 11 martin 418   */
1821 06 Feb 13 nicklas 419   public JSONObject loadBioPlateLocation()
1379 27 Jun 11 martin 420   {
1826 07 Feb 13 nicklas 421     if (jsonWell == null)
1821 06 Feb 13 nicklas 422     {
2134 11 Nov 13 nicklas 423       jsonWell = JsonUtil.getBioWellAsJSON(getItem().getBioWell(), true);
1821 06 Feb 13 nicklas 424     }
1821 06 Feb 13 nicklas 425     return jsonWell;
1379 27 Jun 11 martin 426   }
3146 25 Feb 15 nicklas 427   
3146 25 Feb 15 nicklas 428   /**
3146 25 Feb 15 nicklas 429     Find the next name to give a Lysate child item. This assumes that
3146 25 Feb 15 nicklas 430     all child items are using the naming convention. foo.l, foo.l2, and
3146 25 Feb 15 nicklas 431     so on. NOTE! The first child item have no number!
3146 25 Feb 15 nicklas 432     @return The next unused name
3146 25 Feb 15 nicklas 433     @since 3.2
3146 25 Feb 15 nicklas 434   */
3146 25 Feb 15 nicklas 435   public String getNextLysateName(DbControl dc)
3146 25 Feb 15 nicklas 436   {
3146 25 Feb 15 nicklas 437     Sample sp = getItem();
6193 30 Mar 21 nicklas 438     ItemQuery<Extract> query = null;
6193 30 Mar 21 nicklas 439     if (sp.isInDatabase())
6193 30 Mar 21 nicklas 440     {
6193 30 Mar 21 nicklas 441       query = sp.getExtracts();
6193 30 Mar 21 nicklas 442       Subtype.LYSATE.addFilter(dc, query);
6193 30 Mar 21 nicklas 443       query.setIncludes(Include.ALL);
6193 30 Mar 21 nicklas 444     }
4896 09 Jul 18 nicklas 445     return getNextChildItemName(dc, query, Subtype.LYSATE.getItemSuffix(), true);
3146 25 Feb 15 nicklas 446   }
1379 27 Jun 11 martin 447
3146 25 Feb 15 nicklas 448   /**
3146 25 Feb 15 nicklas 449     Find the next name to give a Histology child item. This assumes that
3146 25 Feb 15 nicklas 450     all child items are using the naming convention. foo.his, foo.his2, and
3146 25 Feb 15 nicklas 451     so on. NOTE! The first child item have no number!
3146 25 Feb 15 nicklas 452     @return The next unused name
3146 25 Feb 15 nicklas 453     @since 3.2
3146 25 Feb 15 nicklas 454   */
3146 25 Feb 15 nicklas 455   public String getNextHistologyName(DbControl dc)
3146 25 Feb 15 nicklas 456   {
3146 25 Feb 15 nicklas 457     Sample sp = getItem();
6193 30 Mar 21 nicklas 458     ItemQuery<Sample> query = null;
6193 30 Mar 21 nicklas 459     if (sp.isInDatabase())
6193 30 Mar 21 nicklas 460     {
6193 30 Mar 21 nicklas 461       query = sp.getChildSamples();
6193 30 Mar 21 nicklas 462       Subtype.HISTOLOGY.addFilter(dc, query);
6193 30 Mar 21 nicklas 463       query.setIncludes(Include.ALL);
6193 30 Mar 21 nicklas 464     }
4896 09 Jul 18 nicklas 465     return getNextChildItemName(dc, query, Subtype.HISTOLOGY.getItemSuffix(), true);
3146 25 Feb 15 nicklas 466   }
3940 16 May 16 nicklas 467   
3940 16 May 16 nicklas 468   /**
3940 16 May 16 nicklas 469     Get the parent case.
3940 16 May 16 nicklas 470     @since 4.5
3940 16 May 16 nicklas 471   */
3940 16 May 16 nicklas 472   public Case getCase()
3940 16 May 16 nicklas 473   {
3940 16 May 16 nicklas 474     Sample specimen = getItem();
3940 16 May 16 nicklas 475     Sample theCase = (Sample)specimen.getParent();
3940 16 May 16 nicklas 476     return Case.get(theCase);
3940 16 May 16 nicklas 477   }
3146 25 Feb 15 nicklas 478
1326 29 Mar 11 nicklas 479 }