/*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2015 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package omero.gateway.model;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static omero.rtypes.*;
import ome.model.units.BigResult;
import omero.model.Length;
import omero.model.LengthI;
import omero.model.Plate;
import omero.model.PlateAcquisition;
import omero.model.PlateI;
import omero.model.ScreenPlateLink;
import omero.model.enums.UnitsLength;
/**
* The data that makes up an <i>OME</i> Plate along with links to its contained
* Well and enclosing Screen as well as the Experimenter that owns this Plate.
*
* @author Jean-Marie Burel <a
* href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author Donald MacDonald <a
* href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
* @version 3.0
* @since 3.0-Beta3
*/
public class PlateData extends DataObject {
/** Indicates that the column or row is a number starting from 1. */
public final static int ASCENDING_NUMBER = 0;
/** Indicates that the column or row is a letter starting from A. */
public final static int ASCENDING_LETTER = 1;
/** Indicates that the column or row is a letter starting from 26 or 16. */
public final static int DESCENDING_NUMBER = 2;
/** Indicates that the column or row is a letter starting from Z or P. */
public final static int DESCENDING_LETTER = 3;
/** Identifies the {@link PlateI#NAME} field. */
public final static String NAME = PlateI.NAME;
/** Identifies the {@link PlateI#DESCRIPTION} field. */
public final static String DESCRIPTION = PlateI.DESCRIPTION;
/** Identifies the {@link PlateI#WELLS} field. */
public final static String WELLS = PlateI.WELLS;
/** Identifies the {@link PlateI#SCREENLINKS} field. */
public final static String SCREEN_LINKS = PlateI.SCREENLINKS;
/** Identifies the {@link PlateI#ANNOTATIONLINKS} field. */
public final static String ANNOTATIONS = PlateI.ANNOTATIONLINKS;
/** Indicates that the convention is to use <code>letter</code>. */
private final static String LETTER_CONVENTION = "letter";
/** Indicates that the convention is to use <code>number</code>. */
private final static String NUMBER_CONVENTION = "number";
/**
* All the Screens that contain this Plate. The elements of this set are
* {@link ScreenData} objects. If this Plate is not contained in any
* Screen, then this set will be empty but never <code>null</code>.
*/
private Set<ScreenData> screens;
/**
* All the Plate Acquisition related to this Plate. The elements of this
* set are {@link PlateAcquisitionData} objects.
* If this Plate does contained in any PlateAcquisition,
* then this set will be empty but never <code>null</code>.
*/
private Set<PlateAcquisitionData> plateAcquisitions;
/**
* Returns the index corresponding to the passed value.
*
* @param value The value to handle.
* @return See above.
*/
private int getSequenceIndex(String value)
{
if (LETTER_CONVENTION.equals(value)) return ASCENDING_LETTER;
else if (NUMBER_CONVENTION.equals(value)) return ASCENDING_NUMBER;
//TODO
return -1;
}
/** Creates a new instance. */
public PlateData()
{
setDirty(true);
setValue(new PlateI());
}
/**
* Creates a new instance.
*
* @param plate Back pointer to the {@link Plate} model object. Mustn't be
* <code>null</code>.
* @throws IllegalArgumentException
* If the object is <code>null</code>.
*/
public PlateData(Plate plate)
{
if (plate == null) {
throw new IllegalArgumentException("Object cannot null.");
}
setValue(plate);
}
// IMMUTABLES
/**
* Sets the name of the plate.
*
* @param name The name of the plate. Mustn't be <code>null</code>.
* @throws IllegalArgumentException
* If the name is <code>null</code>.
*/
public void setName(String name)
{
if (name == null) {
throw new IllegalArgumentException("The name cannot be null.");
}
setDirty(true);
asPlate().setName(rstring(name));
}
/**
* Returns the name of the plate.
*
* @return See above.
*/
public String getName()
{
omero.RString n = asPlate().getName();
if (n == null || n.getValue() == null) {
throw new IllegalStateException(
"The name should never have bee null.");
}
return n.getValue();
}
/**
* Sets the description of the plate.
*
* @param description The description of the plate.
*/
public void setDescription(String description)
{
setDirty(true);
asPlate().setDescription(rstring(description));
}
/**
* Returns the description of the plate.
*
* @return See above.
*/
public String getDescription()
{
omero.RString d = asPlate().getDescription();
return d == null ? null : d.getValue();
}
/**
* Returns the number of annotations linked to the object, key: id of the
* user, value: number of annotation. The map may be <code>null</code> if
* no annotation.
*
* @return See above.
*/
public Map<Long, Long> getAnnotationsCounts()
{
return asPlate().getAnnotationLinksCountPerOwner();
}
/**
* Returns a set of screens containing the plate.
*
* @return See above.
*/
public Set<ScreenData> getScreens()
{
if (screens == null && asPlate().sizeOfScreenLinks() >= 0) {
screens = new HashSet<ScreenData>();
List<ScreenPlateLink> links = asPlate().copyScreenLinks();
for (ScreenPlateLink link : links) {
screens.add(new ScreenData(link.getParent()));
}
}
return screens == null ? null : new HashSet<ScreenData>(screens);
}
/**
* Sets the screens containing the plate.
*
* @param value The set of screens.
*/
public void setScreens(Set<ScreenData> value) {
Set<ScreenData> currentValue = getScreens();
SetMutator<ScreenData> m = new SetMutator<ScreenData>(currentValue,
value);
while (m.moreDeletions()) {
setDirty(true);
asPlate().unlinkScreen(m.nextDeletion().asScreen());
}
while (m.moreAdditions()) {
setDirty(true);
asPlate().linkScreen(m.nextAddition().asScreen());
}
screens = new HashSet<ScreenData>(m.result());
}
/**
* Returns the index indicating how to label a column.
*
* @return See above.
*/
public int getColumnSequenceIndex()
{
omero.RString value = asPlate().getColumnNamingConvention();
if (value == null) return ASCENDING_NUMBER;
String v = value.getValue();
if (v == null) return ASCENDING_NUMBER;
int index = getSequenceIndex(value.getValue().toLowerCase());
if (index == -1) return ASCENDING_NUMBER;
return index;
}
/**
* Returns the index indicating how to label a row.
*
* @return See above.
*/
public int getRowSequenceIndex()
{
omero.RString value = asPlate().getRowNamingConvention();
if (value == null) return ASCENDING_LETTER;
String v = value.getValue();
if (v == null) return ASCENDING_LETTER;
int index = getSequenceIndex(v.toLowerCase());
if (index == -1) return ASCENDING_LETTER;
return index;
}
/**
* Returns the currently selected field or <code>0</code>.
*
* @return See above.
*/
public int getDefaultSample()
{
omero.RInt value = asPlate().getDefaultSample();
if (value == null) return 0;
return value.getValue();
}
/**
* Sets the default sample.
*
* @param value The value to set.
*/
public void setDefaultSample(int value)
{
if (value < 0) value = 0;
asPlate().setDefaultSample(omero.rtypes.rint(value));
}
/**
* Returns the status of the plate.
*
* @return See above.
*/
public String getStatus()
{
omero.RString value = asPlate().getStatus();
if (value == null) return "";
return value.getValue();
}
/**
* Returns the external identifier of the plate.
*
* @return See above.
*/
public String getExternalIdentifier()
{
omero.RString value = asPlate().getExternalIdentifier();
if (value == null) return "";
return value.getValue();
}
/**
* Returns the type of plate e.g. A 384-Well Plate, 96-Well Plate.
*
* @return See above.
*/
public String getPlateType()
{
Plate plate = asPlate();
int c = 0;
int r = 0;
omero.RInt v = plate.getColumns();
if (v != null) c = v.getValue();
v = plate.getRows();
if (v != null) r = v.getValue();
int value = c*r;
if (value <= 0) return "";
return value+"-Well Plate";
}
/**
* Returns the x-coordinate in 2D-space of the well.
*
* @param unit
* The unit (may be null, in which case no conversion will be
* performed)
* @return See above
* @throws BigResult If an arithmetic under-/overflow occurred
*/
public Length getWellOriginX(UnitsLength unit) throws BigResult
{
Length value = asPlate().getWellOriginX();
if (value == null)
return new LengthI(0, UnitsLength.REFERENCEFRAME);
else
return unit == null ? value : new LengthI(value, unit);
}
/**
* Returns the x-coordinate in 2D-space of the well.
*
* @return See above
* @deprecated Replaced by {@link #getWellOriginX(UnitsLength)}
*/
@Deprecated
public double getWellOriginX()
{
Length value = asPlate().getWellOriginX();
if (value == null) return 0;
return value.getValue();
}
/**
* Returns the y-coordinate in 2D-space of the well.
*
* @param unit
* The unit (may be null, in which case no conversion will be
* performed)
* @return See above
* @throws BigResult If an arithmetic under-/overflow occurred
*/
public Length getWellOriginY(UnitsLength unit) throws BigResult
{
Length value = asPlate().getWellOriginY();
if (value == null)
return new LengthI(0, UnitsLength.REFERENCEFRAME);
else
return unit == null ? value : new LengthI(value, unit);
}
/**
* Returns the y-coordinate in 2D-space of the well.
*
* @return See above
* @deprecated Replaced by {@link #getWellOriginY(UnitsLength)}
*/
@Deprecated
public double getWellOriginY()
{
Length value = asPlate().getWellOriginY();
if (value == null) return 0;
return value.getValue();
}
/**
* Returns the plate acquisitions related to this plate.
*
* @return See above.
*/
public Set<PlateAcquisitionData> getPlateAcquisitions()
{
if (plateAcquisitions == null &&
asPlate().sizeOfPlateAcquisitions() >= 0) {
plateAcquisitions = new HashSet<PlateAcquisitionData>();
List<PlateAcquisition> links = asPlate().copyPlateAcquisitions();
for (PlateAcquisition link : links) {
plateAcquisitions.add(new PlateAcquisitionData(link));
}
}
return plateAcquisitions == null ? null :
new HashSet<PlateAcquisitionData>(plateAcquisitions);
}
/**
* Sets the plate acquisition linked to the plate.
*
* @param value The set of plate acquisitions.
*/
public void setPlateAcquisition(Set<PlateAcquisitionData> value)
{
Set<PlateAcquisitionData> currentValue = getPlateAcquisitions();
SetMutator<PlateAcquisitionData>
m = new SetMutator<PlateAcquisitionData>(currentValue, value);
while (m.moreDeletions()) {
setDirty(true);
asPlate().removePlateAcquisition(
(PlateAcquisition) m.nextDeletion().asIObject());
}
while (m.moreAdditions()) {
setDirty(true);
asPlate().addPlateAcquisition(
(PlateAcquisition) m.nextAddition().asIObject());
}
plateAcquisitions = new HashSet<PlateAcquisitionData>(m.result());
}
/**
* Sets the external identifier.
*
* @param value The value to set.
*/
public void setExternalIdentifier(String value)
{
if (value != null && value.trim().length() != 0)
asPlate().setExternalIdentifier(omero.rtypes.rstring(value));
}
/**
* Sets the status.
*
* @param value The value to set.
*/
public void setStatus(String value)
{
if (value != null && value.trim().length() != 0)
asPlate().setStatus(omero.rtypes.rstring(value));
}
}