src/core/net/sf/basedb/core/Plate.java

Code
Comments
Other
Rev Date Author Line
881 06 Jul 05 nicklas 1 /*
881 06 Jul 05 nicklas 2   $Id$
881 06 Jul 05 nicklas 3
3675 16 Aug 07 jari 4   Copyright (C) 2005 Johan Enell, Nicklas Nordborg
4889 06 Apr 09 nicklas 5   Copyright (C) 2006 Jari Häkkinen, Nicklas Nordborg
881 06 Jul 05 nicklas 6
2304 22 May 06 jari 7   This file is part of BASE - BioArray Software Environment.
2304 22 May 06 jari 8   Available at http://base.thep.lu.se/
881 06 Jul 05 nicklas 9
881 06 Jul 05 nicklas 10   BASE is free software; you can redistribute it and/or
881 06 Jul 05 nicklas 11   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 12   as published by the Free Software Foundation; either version 3
881 06 Jul 05 nicklas 13   of the License, or (at your option) any later version.
881 06 Jul 05 nicklas 14
881 06 Jul 05 nicklas 15   BASE is distributed in the hope that it will be useful,
881 06 Jul 05 nicklas 16   but WITHOUT ANY WARRANTY; without even the implied warranty of
881 06 Jul 05 nicklas 17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
881 06 Jul 05 nicklas 18   GNU General Public License for more details.
881 06 Jul 05 nicklas 19
881 06 Jul 05 nicklas 20   You should have received a copy of the GNU General Public License
4517 11 Sep 08 jari 21   along with BASE. If not, see <http://www.gnu.org/licenses/>.
881 06 Jul 05 nicklas 22 */
881 06 Jul 05 nicklas 23 package net.sf.basedb.core;
881 06 Jul 05 nicklas 24
881 06 Jul 05 nicklas 25 import net.sf.basedb.core.data.PlateData;
881 06 Jul 05 nicklas 26 import net.sf.basedb.core.data.PlateEventData;
881 06 Jul 05 nicklas 27 import net.sf.basedb.core.data.PlateCoordinate;
4305 21 May 08 nicklas 28 import net.sf.basedb.core.data.ReporterData;
881 06 Jul 05 nicklas 29 import net.sf.basedb.core.data.WellData;
7381 22 May 17 nicklas 30 import net.sf.basedb.core.hibernate.TypeWrapper;
881 06 Jul 05 nicklas 31 import net.sf.basedb.core.query.Restrictions;
1418 07 Oct 05 nicklas 32 import net.sf.basedb.core.query.Hql;
7014 12 Nov 15 nicklas 33 import net.sf.basedb.core.query.PermissionRestriction;
881 06 Jul 05 nicklas 34
4696 09 Dec 08 nicklas 35 import java.util.Date;
881 06 Jul 05 nicklas 36 import java.util.Map;
1147 30 Aug 05 nicklas 37 import java.util.Set;
1147 30 Aug 05 nicklas 38 import java.util.HashSet;
881 06 Jul 05 nicklas 39
881 06 Jul 05 nicklas 40 /**
881 06 Jul 05 nicklas 41   This class is represents physical plates. A plate must have
881 06 Jul 05 nicklas 42   a {@link PlateType}, which defines the geometry and possible events
881 06 Jul 05 nicklas 43   for the plate.
881 06 Jul 05 nicklas 44   <p>
881 06 Jul 05 nicklas 45   A plate consists of {@link Well}:s which are created at the same
881 06 Jul 05 nicklas 46   time the plate is created. The wells are organised into rows and
881 06 Jul 05 nicklas 47   columns as specified by the plate geometry.
881 06 Jul 05 nicklas 48   <p>
881 06 Jul 05 nicklas 49   A plate is either created directly or as the result of a {@link
881 06 Jul 05 nicklas 50   PlateMapping} operation from other plates. In the first case the
881 06 Jul 05 nicklas 51   wells must be linked to reporters before the plate is saved. In
881 06 Jul 05 nicklas 52   the latter case the linking is done automatically from the
881 06 Jul 05 nicklas 53   source plates.
881 06 Jul 05 nicklas 54
881 06 Jul 05 nicklas 55   @author Nicklas
881 06 Jul 05 nicklas 56   @version 2.0
881 06 Jul 05 nicklas 57   @base.modified $Date$
881 06 Jul 05 nicklas 58 */
881 06 Jul 05 nicklas 59 public class Plate
6874 17 Apr 15 nicklas 60   extends AnnotatedItem
4696 09 Dec 08 nicklas 61   implements Registered
881 06 Jul 05 nicklas 62 {
881 06 Jul 05 nicklas 63   /**
881 06 Jul 05 nicklas 64     The type of item represented by this class.
881 06 Jul 05 nicklas 65     @see Item#PLATE
881 06 Jul 05 nicklas 66     @see #getType()
881 06 Jul 05 nicklas 67   */
881 06 Jul 05 nicklas 68   public static final Item TYPE = Item.PLATE;
881 06 Jul 05 nicklas 69   
881 06 Jul 05 nicklas 70   /**
881 06 Jul 05 nicklas 71     Create a new <code>Plate</code> item.
881 06 Jul 05 nicklas 72
881 06 Jul 05 nicklas 73     @param dc The <code>DbControl</code> which will be used for
881 06 Jul 05 nicklas 74       permission checking and database access
881 06 Jul 05 nicklas 75     @param plateType The type of the new plate
881 06 Jul 05 nicklas 76     @return The new <code>Plate</code> item
881 06 Jul 05 nicklas 77     @throws PermissionDeniedException If the loggged in user
881 06 Jul 05 nicklas 78       doesn't have use permission for the plate type
881 06 Jul 05 nicklas 79     @throws InvalidDataException If the plate type is null
881 06 Jul 05 nicklas 80     @throws BaseException If there is another error
881 06 Jul 05 nicklas 81   */
881 06 Jul 05 nicklas 82   public static Plate getNew(DbControl dc, PlateType plateType)
881 06 Jul 05 nicklas 83     throws BaseException
881 06 Jul 05 nicklas 84   {
881 06 Jul 05 nicklas 85     Plate p = dc.newItem(Plate.class);
881 06 Jul 05 nicklas 86     p.setName("New plate");
881 06 Jul 05 nicklas 87     p.setPlateType(plateType);
881 06 Jul 05 nicklas 88     int rows = plateType.getData().getPlateGeometry().getRows();
881 06 Jul 05 nicklas 89     int columns = plateType.getData().getPlateGeometry().getColumns();
881 06 Jul 05 nicklas 90     PlateData plateData = p.getData();
4696 09 Dec 08 nicklas 91     plateData.setEntryDate(new Date());
881 06 Jul 05 nicklas 92     Map<PlateCoordinate, WellData> wells = plateData.getWells();
881 06 Jul 05 nicklas 93     for (int row = 0; row < rows; ++row)
881 06 Jul 05 nicklas 94     {
881 06 Jul 05 nicklas 95       for (int column = 0; column < columns; ++column)
881 06 Jul 05 nicklas 96       {
881 06 Jul 05 nicklas 97         WellData well = new WellData();
881 06 Jul 05 nicklas 98         well.setPlate(plateData);
881 06 Jul 05 nicklas 99         well.setRow(row);
881 06 Jul 05 nicklas 100         well.setColumn(column);
881 06 Jul 05 nicklas 101         wells.put(new PlateCoordinate(row, column), well);
881 06 Jul 05 nicklas 102       }
881 06 Jul 05 nicklas 103     }
881 06 Jul 05 nicklas 104     return p;
881 06 Jul 05 nicklas 105   }
881 06 Jul 05 nicklas 106
881 06 Jul 05 nicklas 107   /**
881 06 Jul 05 nicklas 108     Get a <code>Plate</code> item when you know the id.
881 06 Jul 05 nicklas 109
881 06 Jul 05 nicklas 110     @param dc The <code>DbControl</code> which will be used for
881 06 Jul 05 nicklas 111       permission checking and database access.
881 06 Jul 05 nicklas 112     @param id The id of the item to load
881 06 Jul 05 nicklas 113     @return The <code>Plate</code> item
881 06 Jul 05 nicklas 114     @throws ItemNotFoundException If an item with the specified 
881 06 Jul 05 nicklas 115       id is not found
881 06 Jul 05 nicklas 116     @throws PermissionDeniedException If the logged in user doesn't 
881 06 Jul 05 nicklas 117       have {@link Permission#READ} permission to the item
881 06 Jul 05 nicklas 118     @throws BaseException If there is another error
881 06 Jul 05 nicklas 119   */
881 06 Jul 05 nicklas 120   public static Plate getById(DbControl dc, int id)
881 06 Jul 05 nicklas 121     throws ItemNotFoundException, PermissionDeniedException, BaseException
881 06 Jul 05 nicklas 122   {
881 06 Jul 05 nicklas 123     Plate p = dc.loadItem(Plate.class, id);
881 06 Jul 05 nicklas 124     if (p == null) throw new ItemNotFoundException("Plate[id="+id+"]");
881 06 Jul 05 nicklas 125     return p;
881 06 Jul 05 nicklas 126   }
881 06 Jul 05 nicklas 127
881 06 Jul 05 nicklas 128   /**
1719 15 Dec 05 enell 129     Get a query that returns plates.
1418 07 Oct 05 nicklas 130     @return An {@link ItemQuery} object
881 06 Jul 05 nicklas 131   */
1418 07 Oct 05 nicklas 132   public static ItemQuery<Plate> getQuery()
881 06 Jul 05 nicklas 133   {
1418 07 Oct 05 nicklas 134     return new ItemQuery<Plate>(Plate.class);
881 06 Jul 05 nicklas 135   }
881 06 Jul 05 nicklas 136
881 06 Jul 05 nicklas 137   Plate(PlateData plateData)
881 06 Jul 05 nicklas 138   {
881 06 Jul 05 nicklas 139     super(plateData);
881 06 Jul 05 nicklas 140   }
881 06 Jul 05 nicklas 141
6874 17 Apr 15 nicklas 142   @Override
6874 17 Apr 15 nicklas 143   PlateData getData()
6874 17 Apr 15 nicklas 144   {
6874 17 Apr 15 nicklas 145     return (PlateData)getBasicData();
6874 17 Apr 15 nicklas 146   }
881 06 Jul 05 nicklas 147   /*
881 06 Jul 05 nicklas 148     From the Identifiable interface
881 06 Jul 05 nicklas 149     -------------------------------------------
881 06 Jul 05 nicklas 150   */
6127 14 Sep 12 nicklas 151   @Override
881 06 Jul 05 nicklas 152   public Item getType()
881 06 Jul 05 nicklas 153   {
881 06 Jul 05 nicklas 154     return TYPE;
881 06 Jul 05 nicklas 155   }
881 06 Jul 05 nicklas 156   // -------------------------------------------
1147 30 Aug 05 nicklas 157   /**
1147 30 Aug 05 nicklas 158     Get the parent plates, if any.
1147 30 Aug 05 nicklas 159   */
6127 14 Sep 12 nicklas 160   @Override
1147 30 Aug 05 nicklas 161   public Set<Annotatable> getAnnotatableParents()
1147 30 Aug 05 nicklas 162     throws BaseException
1147 30 Aug 05 nicklas 163   {
1147 30 Aug 05 nicklas 164     Set<Annotatable> annotatable = new HashSet<Annotatable>();
2586 24 Aug 06 nicklas 165     ItemQuery<Plate> plates = getParentPlates();
5319 20 Apr 10 nicklas 166     plates.include(Include.ALL);
2586 24 Aug 06 nicklas 167     annotatable.addAll(plates.list(getDbControl()));
1147 30 Aug 05 nicklas 168     return annotatable;
1147 30 Aug 05 nicklas 169   }
1147 30 Aug 05 nicklas 170   // -------------------------------------------
881 06 Jul 05 nicklas 171   /*
4696 09 Dec 08 nicklas 172     From the Registered interface
4696 09 Dec 08 nicklas 173     -------------------------------------------
4696 09 Dec 08 nicklas 174   */
6127 14 Sep 12 nicklas 175   @Override
4696 09 Dec 08 nicklas 176   public Date getEntryDate()
4696 09 Dec 08 nicklas 177   {
4696 09 Dec 08 nicklas 178     return DateUtil.copy(getData().getEntryDate());
4696 09 Dec 08 nicklas 179   }
7308 13 Mar 17 nicklas 180   @Override
7308 13 Mar 17 nicklas 181   public void setEntryDate(Date entryDate)
7308 13 Mar 17 nicklas 182   {
7308 13 Mar 17 nicklas 183     if (isInDatabase()) 
7308 13 Mar 17 nicklas 184     {
7308 13 Mar 17 nicklas 185       throw new PermissionDeniedException("Not allowed to change entryDate of " + this);
7308 13 Mar 17 nicklas 186     }
7308 13 Mar 17 nicklas 187     getData().setEntryDate(DateUtil.setDateOrToday(entryDate));
7308 13 Mar 17 nicklas 188   }
4696 09 Dec 08 nicklas 189   // -------------------------------------------
4696 09 Dec 08 nicklas 190   /*
881 06 Jul 05 nicklas 191     From the BasicItem class
881 06 Jul 05 nicklas 192     -------------------------------------------
881 06 Jul 05 nicklas 193   */
881 06 Jul 05 nicklas 194   /**
881 06 Jul 05 nicklas 195     Check if:
881 06 Jul 05 nicklas 196     <ul>
881 06 Jul 05 nicklas 197     <li>another <code>Plate</code> has been created from this one (via a {@link PlateMapping})
881 06 Jul 05 nicklas 198     <li>any {@link ArrayDesign}:s are using this plate
881 06 Jul 05 nicklas 199     </ul>
881 06 Jul 05 nicklas 200     Wells are deleted automatically.
881 06 Jul 05 nicklas 201   */
6127 14 Sep 12 nicklas 202   @Override
881 06 Jul 05 nicklas 203   public boolean isUsed()
881 06 Jul 05 nicklas 204     throws BaseException
881 06 Jul 05 nicklas 205   {
881 06 Jul 05 nicklas 206     org.hibernate.Session session = getDbControl().getHibernateSession();
7381 22 May 17 nicklas 207     org.hibernate.query.Query<Long> query = HibernateUtil.getPredefinedQuery(session, 
7381 22 May 17 nicklas 208       "GET_CHILDPLATES_FOR_PLATE", Long.class, "count(*)");
881 06 Jul 05 nicklas 209     /*
2898 13 Nov 06 nicklas 210       SELECT {1}
881 06 Jul 05 nicklas 211       FROM PlateData p
881 06 Jul 05 nicklas 212       JOIN p.parents pp
881 06 Jul 05 nicklas 213       WHERE pp = :plate
881 06 Jul 05 nicklas 214     */
7381 22 May 17 nicklas 215     query.setParameter("plate", getId(), TypeWrapper.H_INTEGER);
7381 22 May 17 nicklas 216     boolean used = HibernateUtil.loadData(query) > 0;
881 06 Jul 05 nicklas 217     if (!used)
881 06 Jul 05 nicklas 218     {
2898 13 Nov 06 nicklas 219       query = HibernateUtil.getPredefinedQuery(session, 
7381 22 May 17 nicklas 220         "GET_ARRAYDESIGNS_FOR_PLATE", Long.class, "count(*)");
1148 30 Aug 05 nicklas 221       /*
2898 13 Nov 06 nicklas 222         SELECT {1}
1148 30 Aug 05 nicklas 223         FROM ArrayDesignData ad
1148 30 Aug 05 nicklas 224         JOIN ad.plates p
1148 30 Aug 05 nicklas 225         WHERE p = :plate
1148 30 Aug 05 nicklas 226       */
7381 22 May 17 nicklas 227       query.setParameter("plate", getId(), TypeWrapper.H_INTEGER);
7381 22 May 17 nicklas 228       used = HibernateUtil.loadData(query) > 0;
881 06 Jul 05 nicklas 229     }
2382 14 Jun 06 nicklas 230     return used || super.isUsed();
881 06 Jul 05 nicklas 231   }
2898 13 Nov 06 nicklas 232   /**
2898 13 Nov 06 nicklas 233     Get all:
2898 13 Nov 06 nicklas 234     <ul>
2898 13 Nov 06 nicklas 235     <li>Child plates
2898 13 Nov 06 nicklas 236     <li>{@link ArrayDesign}:s using this plate 
6881 21 Apr 15 nicklas 237     </ul>
2898 13 Nov 06 nicklas 238     @since 2.2
2898 13 Nov 06 nicklas 239   */
2898 13 Nov 06 nicklas 240   @Override
2898 13 Nov 06 nicklas 241   public Set<ItemProxy> getUsingItems()
2898 13 Nov 06 nicklas 242   {
2898 13 Nov 06 nicklas 243     Set<ItemProxy> using = super.getUsingItems();
2898 13 Nov 06 nicklas 244     org.hibernate.Session session = getDbControl().getHibernateSession();
2898 13 Nov 06 nicklas 245     
2898 13 Nov 06 nicklas 246     // Plates
7381 22 May 17 nicklas 247     org.hibernate.query.Query<Integer> query = HibernateUtil.getPredefinedQuery(session, 
7381 22 May 17 nicklas 248         "GET_CHILDPLATES_FOR_PLATE", Integer.class, "p.id");
2898 13 Nov 06 nicklas 249       /*
2898 13 Nov 06 nicklas 250         SELECT {1}
2898 13 Nov 06 nicklas 251         FROM PlateData p
2898 13 Nov 06 nicklas 252         JOIN p.parents pp
2898 13 Nov 06 nicklas 253         WHERE pp = :plate
2898 13 Nov 06 nicklas 254       */
7381 22 May 17 nicklas 255     query.setParameter("plate", getId(), TypeWrapper.H_INTEGER);
2898 13 Nov 06 nicklas 256     addUsingItems(using, Item.PLATE, query);
2898 13 Nov 06 nicklas 257     
2898 13 Nov 06 nicklas 258     // Array designs
2898 13 Nov 06 nicklas 259     query = HibernateUtil.getPredefinedQuery(session, 
7381 22 May 17 nicklas 260         "GET_ARRAYDESIGNS_FOR_PLATE", Integer.class, "ad.id");
2898 13 Nov 06 nicklas 261       /*
2898 13 Nov 06 nicklas 262         SELECT {1}
2898 13 Nov 06 nicklas 263         FROM ArrayDesignData ad
2898 13 Nov 06 nicklas 264         JOIN ad.plates p
2898 13 Nov 06 nicklas 265         WHERE p = :plate
2898 13 Nov 06 nicklas 266       */
7381 22 May 17 nicklas 267     query.setParameter("plate", getId(), TypeWrapper.H_INTEGER);
2898 13 Nov 06 nicklas 268     addUsingItems(using, Item.ARRAYDESIGN, query);
2898 13 Nov 06 nicklas 269     
2898 13 Nov 06 nicklas 270     return using;
2898 13 Nov 06 nicklas 271   }
881 06 Jul 05 nicklas 272   // -------------------------------------------
881 06 Jul 05 nicklas 273
881 06 Jul 05 nicklas 274   /**
881 06 Jul 05 nicklas 275     Get the {@link PlateType} of this plate.
881 06 Jul 05 nicklas 276     @return The <code>PlateType</code> item
881 06 Jul 05 nicklas 277     @throws PermissionDeniedException If the logged in user doesn't have
881 06 Jul 05 nicklas 278       {@link Permission#READ} permission for the plate type
881 06 Jul 05 nicklas 279     @throws BaseException If there is another error
881 06 Jul 05 nicklas 280   */
881 06 Jul 05 nicklas 281   public PlateType getPlateType()
881 06 Jul 05 nicklas 282     throws PermissionDeniedException, BaseException
881 06 Jul 05 nicklas 283   {
881 06 Jul 05 nicklas 284     return getDbControl().getItem(PlateType.class, getData().getPlateType()); 
881 06 Jul 05 nicklas 285   }
881 06 Jul 05 nicklas 286   
881 06 Jul 05 nicklas 287   /**
881 06 Jul 05 nicklas 288     Set the plate type of this plate.
881 06 Jul 05 nicklas 289     @throws PermissionDeniedException If the logged in user
881 06 Jul 05 nicklas 290       doesn't have use permission for the plate type
881 06 Jul 05 nicklas 291     @throws InvalidDataException If the plate type is null
881 06 Jul 05 nicklas 292   */
881 06 Jul 05 nicklas 293   private void setPlateType(PlateType plateType)
881 06 Jul 05 nicklas 294     throws PermissionDeniedException, InvalidDataException
881 06 Jul 05 nicklas 295   {
881 06 Jul 05 nicklas 296     if (plateType == null) throw new InvalidUseOfNullException("plateType");
881 06 Jul 05 nicklas 297     plateType.checkPermission(Permission.USE);
881 06 Jul 05 nicklas 298     getData().setPlateType(plateType.getData());
881 06 Jul 05 nicklas 299   }
881 06 Jul 05 nicklas 300   
881 06 Jul 05 nicklas 301   /**
881 06 Jul 05 nicklas 302     Get the {@link PlateMapping} used to create this plate.
881 06 Jul 05 nicklas 303     @return The <code>PlateMapping</code> item, or null if this plate was not
881 06 Jul 05 nicklas 304       created using a mapping
881 06 Jul 05 nicklas 305     @throws PermissionDeniedException If the logged in user doesn't have
881 06 Jul 05 nicklas 306       read permission to the plate mapping
881 06 Jul 05 nicklas 307     @throws BaseException If there is another error
881 06 Jul 05 nicklas 308   */
881 06 Jul 05 nicklas 309   public PlateMapping getPlateMapping()
881 06 Jul 05 nicklas 310     throws PermissionDeniedException, BaseException
881 06 Jul 05 nicklas 311   {
881 06 Jul 05 nicklas 312     return getDbControl().getItem(PlateMapping.class, getData().getPlateMapping()); 
881 06 Jul 05 nicklas 313   }
1148 30 Aug 05 nicklas 314
881 06 Jul 05 nicklas 315   /**
1148 30 Aug 05 nicklas 316     If the plate was created by a plate mapping, this is the index
1148 30 Aug 05 nicklas 317     of this plate in the list of created plates. First plate have index 0.
881 06 Jul 05 nicklas 318   */
1148 30 Aug 05 nicklas 319   public int getDestinationIndex()
881 06 Jul 05 nicklas 320   {
1148 30 Aug 05 nicklas 321     return getData().getDestinationIndex();
881 06 Jul 05 nicklas 322   }
881 06 Jul 05 nicklas 323   
881 06 Jul 05 nicklas 324   /**
881 06 Jul 05 nicklas 325     The maximum length of the barcode that can be stored in the
881 06 Jul 05 nicklas 326     database. Check the length against this value before calling the
881 06 Jul 05 nicklas 327     {@link #setBarcode(String)} method to avoid exceptions.
881 06 Jul 05 nicklas 328   */
1659 24 Nov 05 nicklas 329   public static final int MAX_BARCODE_LENGTH = PlateData.MAX_BARCODE_LENGTH;
881 06 Jul 05 nicklas 330   /**
881 06 Jul 05 nicklas 331     Get the barcode of this plate. The barcode is not used by the 
881 06 Jul 05 nicklas 332     core and it is not required that it is unique.
881 06 Jul 05 nicklas 333   */
881 06 Jul 05 nicklas 334   public String getBarcode()
881 06 Jul 05 nicklas 335   {
881 06 Jul 05 nicklas 336     return getData().getBarcode();
881 06 Jul 05 nicklas 337   }
881 06 Jul 05 nicklas 338   /**
881 06 Jul 05 nicklas 339     Set the barcode for the plate. Null is allowed but the value 
881 06 Jul 05 nicklas 340     can't be longer than the value specified by
881 06 Jul 05 nicklas 341     the {@link #MAX_BARCODE_LENGTH} constant. Normally,
881 06 Jul 05 nicklas 342     this should be a unique value among all plates, but the core does not
881 06 Jul 05 nicklas 343     check this.
881 06 Jul 05 nicklas 344     @param barcode The new barcode for the plate
881 06 Jul 05 nicklas 345     @throws PermissionDeniedException If the logged in user doesn't
881 06 Jul 05 nicklas 346       have write permission
881 06 Jul 05 nicklas 347     @throws InvalidDataException If the value is too long
881 06 Jul 05 nicklas 348   */
881 06 Jul 05 nicklas 349   public void setBarcode(String barcode)
881 06 Jul 05 nicklas 350     throws PermissionDeniedException, InvalidDataException
881 06 Jul 05 nicklas 351   {
881 06 Jul 05 nicklas 352     checkPermission(Permission.WRITE);
881 06 Jul 05 nicklas 353     getData().setBarcode(StringUtil.setNullableString(barcode, "barcode", MAX_BARCODE_LENGTH));
881 06 Jul 05 nicklas 354   }
881 06 Jul 05 nicklas 355   
881 06 Jul 05 nicklas 356   /**
881 06 Jul 05 nicklas 357     Check if the plate has been destroyed. A destroyed plate
881 06 Jul 05 nicklas 358     can't be used by a {@link PlateMapping} to create new plates
881 06 Jul 05 nicklas 359     or to create {@link ArrayDesign}:s.
881 06 Jul 05 nicklas 360   */
881 06 Jul 05 nicklas 361   public boolean isDestroyed()
881 06 Jul 05 nicklas 362   {
881 06 Jul 05 nicklas 363     return getData().isDestroyed();
881 06 Jul 05 nicklas 364   }
881 06 Jul 05 nicklas 365   
881 06 Jul 05 nicklas 366   /**
881 06 Jul 05 nicklas 367     Set the destroyed flag. A destroyed plate
881 06 Jul 05 nicklas 368     can't be used by a {@link PlateMapping} to create new plates
881 06 Jul 05 nicklas 369     or to create {@link ArrayDesign}:s.
4020 29 Nov 07 martin 370      @param destroyed TRUE if the plate is destroyed, FALSE otherwise. 
4020 29 Nov 07 martin 371      @throws PermissionDeniedException If the logged in user doesn't 
4020 29 Nov 07 martin 372        have write permission on the item.
881 06 Jul 05 nicklas 373   */
881 06 Jul 05 nicklas 374   public void setDestroyed(boolean destroyed)
881 06 Jul 05 nicklas 375     throws PermissionDeniedException
881 06 Jul 05 nicklas 376   {
881 06 Jul 05 nicklas 377     checkPermission(Permission.WRITE);
881 06 Jul 05 nicklas 378     getData().setDestroyed(destroyed);
881 06 Jul 05 nicklas 379   }
881 06 Jul 05 nicklas 380   
881 06 Jul 05 nicklas 381   /**
1148 30 Aug 05 nicklas 382     Get a query returning the parent plates of this plate. A plate
1148 30 Aug 05 nicklas 383     has parents if it was created by a {@link PlateMapping}.
1418 07 Oct 05 nicklas 384     @return An <code>ItemQuery</code> object
1148 30 Aug 05 nicklas 385   */
1418 07 Oct 05 nicklas 386   public ItemQuery<Plate> getParentPlates()
1148 30 Aug 05 nicklas 387   {
1418 07 Oct 05 nicklas 388     ItemQuery<Plate> query = Plate.getQuery();
1418 07 Oct 05 nicklas 389     query.joinPermanent(Hql.innerJoin("children", "c"));
1418 07 Oct 05 nicklas 390     query.restrictPermanent(
1418 07 Oct 05 nicklas 391       Restrictions.eq(
1418 07 Oct 05 nicklas 392         Hql.alias("c"), 
1418 07 Oct 05 nicklas 393         Hql.entity(this)
1418 07 Oct 05 nicklas 394       )
1418 07 Oct 05 nicklas 395     );
1148 30 Aug 05 nicklas 396     return query;
1148 30 Aug 05 nicklas 397   }
1148 30 Aug 05 nicklas 398   
1148 30 Aug 05 nicklas 399   /**
1148 30 Aug 05 nicklas 400     If this plate was created by a {@link PlateMapping} and the specified plate
1148 30 Aug 05 nicklas 401     is a parent, get the index of the parent plate in the list
1148 30 Aug 05 nicklas 402     of source plates used by the plate mapping. If the plate is not a parent, -1
1148 30 Aug 05 nicklas 403     is returned.
4040 05 Dec 07 martin 404      @param parent The plate to get source index of, if it's a parent. Null is not allowed. 
1157 30 Aug 05 nicklas 405     @return The source index or -1 if the plate is not a parent plate
1148 30 Aug 05 nicklas 406     @throws InvalidDataException If the parent is null
1148 30 Aug 05 nicklas 407   */
1148 30 Aug 05 nicklas 408   public int getSourceIndex(Plate parent)
1148 30 Aug 05 nicklas 409     throws InvalidDataException
1148 30 Aug 05 nicklas 410   {
1148 30 Aug 05 nicklas 411     if (parent == null) throw new InvalidDataException("parent");
1148 30 Aug 05 nicklas 412     return IntegerUtil.getInt(getData().getParents().get(parent.getData()), -1);
1148 30 Aug 05 nicklas 413   }
1148 30 Aug 05 nicklas 414   
1148 30 Aug 05 nicklas 415   /**
1148 30 Aug 05 nicklas 416     Get a query returning the child plates of this plate. 
1418 07 Oct 05 nicklas 417     @return An <code>ItemQuery</code> object
1148 30 Aug 05 nicklas 418   */
1418 07 Oct 05 nicklas 419   public ItemQuery<Plate> getChildPlates()
1148 30 Aug 05 nicklas 420   {
1418 07 Oct 05 nicklas 421     ItemQuery<Plate> query = Plate.getQuery();
1418 07 Oct 05 nicklas 422     query.joinPermanent(Hql.innerJoin("parents", "p"));
1418 07 Oct 05 nicklas 423     query.restrictPermanent(
1418 07 Oct 05 nicklas 424       Restrictions.eq(
1418 07 Oct 05 nicklas 425         Hql.index("p", null), 
1418 07 Oct 05 nicklas 426         Hql.entity(this)
1418 07 Oct 05 nicklas 427       )
1418 07 Oct 05 nicklas 428     );
1148 30 Aug 05 nicklas 429     return query;
1148 30 Aug 05 nicklas 430   }
1148 30 Aug 05 nicklas 431   
1148 30 Aug 05 nicklas 432   /**
881 06 Jul 05 nicklas 433     Get the event for the specified event type. If no
881 06 Jul 05 nicklas 434     event for that type exist a new one is created.
1655 23 Nov 05 nicklas 435     @param eventType The event type to get or create the event for
881 06 Jul 05 nicklas 436     @return The <code>PlateEvent</code> item
881 06 Jul 05 nicklas 437     @throws PermissionDeniedException If the logged in user
881 06 Jul 05 nicklas 438       doesn't have read permission for an existing event
881 06 Jul 05 nicklas 439       or doesn't have write permission if a new event must be 
881 06 Jul 05 nicklas 440       created
881 06 Jul 05 nicklas 441     @throws InvalidDataException If the event type is null or
881 06 Jul 05 nicklas 442       doesn't belong to the same {@link PlateType} as the plate
881 06 Jul 05 nicklas 443     @throws BaseException If there is another error
1655 23 Nov 05 nicklas 444     @see #hasEvent(PlateEventType)
1655 23 Nov 05 nicklas 445     @see #getEvents()
881 06 Jul 05 nicklas 446   */
881 06 Jul 05 nicklas 447   public PlateEvent getEvent(PlateEventType eventType)
881 06 Jul 05 nicklas 448     throws PermissionDeniedException, InvalidDataException, BaseException
881 06 Jul 05 nicklas 449   {
881 06 Jul 05 nicklas 450     if (eventType == null) throw new InvalidUseOfNullException("eventType");
881 06 Jul 05 nicklas 451     PlateEventData eventData = getData().getEvents().get(eventType.getData());
881 06 Jul 05 nicklas 452     PlateEvent event = null;
881 06 Jul 05 nicklas 453     if (eventData == null)
881 06 Jul 05 nicklas 454     {
881 06 Jul 05 nicklas 455       event = PlateEvent.getNew(getDbControl(), this, eventType);
881 06 Jul 05 nicklas 456     }
881 06 Jul 05 nicklas 457     else
881 06 Jul 05 nicklas 458     {
881 06 Jul 05 nicklas 459       event = getDbControl().getItem(PlateEvent.class, eventData);
881 06 Jul 05 nicklas 460     }
881 06 Jul 05 nicklas 461     return event;
881 06 Jul 05 nicklas 462   }
1655 23 Nov 05 nicklas 463   
1655 23 Nov 05 nicklas 464   /**
1655 23 Nov 05 nicklas 465     Check if an event for the specified event type has been created
1655 23 Nov 05 nicklas 466     for this plate. A plate may only have one event of each type.
1655 23 Nov 05 nicklas 467     @param eventType The event type to check
1655 23 Nov 05 nicklas 468     @return TRUE if an event of the specified type exists, FALSE otherwise
1655 23 Nov 05 nicklas 469     @see #getEvent(PlateEventType)
1655 23 Nov 05 nicklas 470     @see #getEvents()
1655 23 Nov 05 nicklas 471   */
1655 23 Nov 05 nicklas 472   public boolean hasEvent(PlateEventType eventType)
1655 23 Nov 05 nicklas 473   {
1655 23 Nov 05 nicklas 474     if (eventType == null) return false;
1655 23 Nov 05 nicklas 475     return getData().getEvents().containsKey(eventType.getData());
1655 23 Nov 05 nicklas 476   }
1655 23 Nov 05 nicklas 477   
881 06 Jul 05 nicklas 478
881 06 Jul 05 nicklas 479   /**
1418 07 Oct 05 nicklas 480     Get a query that returns all event types for this plate type.
1418 07 Oct 05 nicklas 481     @return An {@link ItemQuery} object
881 06 Jul 05 nicklas 482     @throws BaseException If there is an error
881 06 Jul 05 nicklas 483   */
1418 07 Oct 05 nicklas 484   public ItemQuery<PlateEvent> getEvents()
881 06 Jul 05 nicklas 485   {
1418 07 Oct 05 nicklas 486     return PlateEvent.getQuery(this);
881 06 Jul 05 nicklas 487   }
881 06 Jul 05 nicklas 488   
881 06 Jul 05 nicklas 489   /**
881 06 Jul 05 nicklas 490     Get the well on the specified plate coordinate.
1568 04 Nov 05 enell 491     @param row The row coordinate of the well. Starting at 0.
1568 04 Nov 05 enell 492     @param column The column coordinate of the well. Starting at 0.
881 06 Jul 05 nicklas 493     @return A <code>Well</code> item or null if the coordinates
881 06 Jul 05 nicklas 494       are outside the range specified by the geometry
881 06 Jul 05 nicklas 495     @throws PermissionDeniedException If the logged in user doesn't
881 06 Jul 05 nicklas 496       have read permission for the well
881 06 Jul 05 nicklas 497     @throws BaseException If there is another error
881 06 Jul 05 nicklas 498   */
881 06 Jul 05 nicklas 499   public Well getWell(int row, int column)
881 06 Jul 05 nicklas 500     throws PermissionDeniedException, BaseException
881 06 Jul 05 nicklas 501   {
881 06 Jul 05 nicklas 502     WellData wellData = getData().getWells().get(new PlateCoordinate(row, column));
881 06 Jul 05 nicklas 503     return getDbControl().getItem(Well.class, wellData);
881 06 Jul 05 nicklas 504   }
881 06 Jul 05 nicklas 505   
881 06 Jul 05 nicklas 506   /**
1418 07 Oct 05 nicklas 507     Get a query returning all wells for this plate.
1418 07 Oct 05 nicklas 508     @return An <code>ItemQuery</code> object
881 06 Jul 05 nicklas 509     @throws BaseException If there is an error
881 06 Jul 05 nicklas 510   */
1418 07 Oct 05 nicklas 511   public ItemQuery<Well> getWells()
881 06 Jul 05 nicklas 512   {
1418 07 Oct 05 nicklas 513     return Well.getQuery(this);
881 06 Jul 05 nicklas 514   }
881 06 Jul 05 nicklas 515   
4305 21 May 08 nicklas 516   /**
4305 21 May 08 nicklas 517     Get a query that returns the reporters on this plate. The query
4305 21 May 08 nicklas 518     is rooted at the wells, which means that:
4305 21 May 08 nicklas 519     <ul>
4305 21 May 08 nicklas 520     <li>All filters, sorting, etc. that works for {@link #getWells()} can be 
4305 21 May 08 nicklas 521       used without modifications on this query.
4305 21 May 08 nicklas 522     <li>The same reporter may be returned multiple times if it is present on several
4305 21 May 08 nicklas 523       wells.
4305 21 May 08 nicklas 524     <li>'Null' values may be returned if there are wells without a reporter
4305 21 May 08 nicklas 525     </ul>
4305 21 May 08 nicklas 526     
4305 21 May 08 nicklas 527     @return A {@link DataQuery} object
4305 21 May 08 nicklas 528     @since 2.8
4305 21 May 08 nicklas 529   */
4305 21 May 08 nicklas 530   public DataQuery<ReporterData> getReporters()
4305 21 May 08 nicklas 531   {
4305 21 May 08 nicklas 532     DataQuery<ReporterData> query = 
4305 21 May 08 nicklas 533       new DataQuery<ReporterData>(ReporterData.class, Item.WELL, null, "reporter");
7014 12 Nov 15 nicklas 534     // We allow reporters without READ permission unless it has been explicitely DENIED
7014 12 Nov 15 nicklas 535     query.restrictPermanent(new PermissionRestriction(Permission.DENIED, Item.REPORTER));
4305 21 May 08 nicklas 536     query.restrictPermanent(
4305 21 May 08 nicklas 537         Restrictions.eq(
4305 21 May 08 nicklas 538           Hql.property("plate"),
4305 21 May 08 nicklas 539           Hql.entity(this)
4305 21 May 08 nicklas 540         )
4305 21 May 08 nicklas 541       );
4305 21 May 08 nicklas 542     return query;
4305 21 May 08 nicklas 543   }
4305 21 May 08 nicklas 544   
881 06 Jul 05 nicklas 545 }