// $HeadURL$ // $Id$ // // Copyright © 2006, 2010, 2011, 2012 by the President and Fellows of Harvard College. // // Screensaver is an open-source project developed by the ICCB-L and NSRB labs // at Harvard Medical School. This software is distributed under the terms of // the GNU General Public License. package edu.harvard.med.screensaver.model.libraries; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; import com.google.common.base.Predicate; import edu.harvard.med.screensaver.util.AlphabeticCounter; @Embeddable public class WellName implements Comparable<WellName> { // static members public static Pattern WELL_NAME_PATTERN = Pattern.compile("([A-Z]+)([0-9]+)", Pattern.CASE_INSENSITIVE); public static final Predicate<WellName> makeIsNonExtantWellNamePredicate(final PlateSize plateSize) { return new Predicate<WellName>() { public boolean apply(WellName w) { return w.getRowIndex() >= plateSize.getRows() || w.getColumnIndex() >= plateSize.getColumns(); } }; } public static String toString(int rowIndex, int columnIndex) { return getRowLabel(rowIndex) + getColumnLabel(columnIndex); } // instance data members private int _rowIndex; private int _columnIndex; private String _wellName; // public constructors and methods /** * @motivation for Hibernate */ private WellName() { } /** * * @param rowIndex * @param columnIndex 0 based index (column label is converted to 1 based) */ public WellName(int rowIndex, int columnIndex) { if (columnIndex < 0 || rowIndex < 0) { throw new IllegalArgumentException("row or column out of range"); } _rowIndex = rowIndex; _columnIndex = columnIndex; _wellName = toString(_rowIndex, _columnIndex); } public WellName(String wellName) { setName(wellName); } /** * Return the 0-based index of the column. */ @Transient public int getColumnIndex() { return _columnIndex; } private void setColumnIndex(int columnIndex) { if (columnIndex < 0) { throw new IllegalArgumentException("column index" + columnIndex + " is negative"); } _columnIndex = columnIndex; } /** * Return the 0-based index of the row. */ @Transient public int getRowIndex() { return _rowIndex; } private void setRowIndex(int rowIndex) { if (rowIndex < 0) { throw new IllegalArgumentException("row index" + rowIndex + " is negative"); } _rowIndex = rowIndex; } @Transient public String getRowLabel() { return getRowLabel(_rowIndex); } @Transient public String getColumnLabel() { return getColumnLabel(_columnIndex); } public static String getRowLabel(int rowIndex) { return AlphabeticCounter.toLabel(rowIndex); } public static String getColumnLabel(int columnIndex) { return String.format("%02d", columnIndex + 1); } private void setName(String wellName) { Matcher matcher = WELL_NAME_PATTERN.matcher(wellName); if (matcher.matches()) { setRowIndex(parseRowLabel(matcher.group(1))); setColumnIndex(parseColumnLabel(matcher.group(2))); } else { throw new IllegalArgumentException("illegal well name '" + wellName + "'"); } _wellName = toString(_rowIndex, _columnIndex); } public static int parseColumnLabel(String columnLabel) { return Integer.parseInt(columnLabel) - 1; } public static int parseRowLabel(String rowLabel) { return AlphabeticCounter.toIndex(rowLabel.toUpperCase()); } // TODO: length only works up to 384 well plates; increase length to accommodate labels for max plate size @Column(name="wellName", length=3) public String getName() { return _wellName; } public boolean isValidForPlateSize(PlateSize plateSize) { return makeIsNonExtantWellNamePredicate(plateSize).apply(this); } public String toString() { return _wellName; } @Override public int hashCode() { return _wellName.hashCode(); } @Override public boolean equals(Object other) { if (other == null) { return false; } if (other == this) { return true; } return _rowIndex == ((WellName) other)._rowIndex && _columnIndex == ((WellName) other)._columnIndex; } public int compareTo(WellName other) { return _rowIndex < other._rowIndex ? -1 : _rowIndex > other._rowIndex ? 1 : _columnIndex < other._columnIndex ? -1 : _columnIndex > other._columnIndex ? 1 : 0; } }