All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.automation.SimpleWell Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.automation;


import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

import com.hfg.bio.HfgBioXML;
import com.hfg.exception.InvalidValueException;
import com.hfg.units.Quantity;
import com.hfg.units.QuantityType;
import com.hfg.util.StringUtil;
import com.hfg.util.collection.CollectionUtil;
import com.hfg.util.collection.OrderedSet;
import com.hfg.xml.HfgXMLSerializable;
import com.hfg.xml.XMLNode;
import com.hfg.xml.XMLTag;

//------------------------------------------------------------------------------
/**
 Generic well in a plate.
 
@author J. Alex Taylor, hairyfatguy.com
*/ //------------------------------------------------------------------------------ // com.hfg XML/HTML Coding Library // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com // [email protected] //------------------------------------------------------------------------------ public class SimpleWell implements Well, Cloneable { private WellRef mLocation; private WellType mType; private Set mSamples; private Float mRawResult; private Quantity mVolume; private SimplePlate mPlate; private EnumSet mFlags; public enum Flag { SELECTED, ERROR } //########################################################################### // CONSTRUCTORS //########################################################################### //--------------------------------------------------------------------------- public SimpleWell(WellRef inLocation) { mLocation = inLocation; } //--------------------------------------------------------------------------- public SimpleWell(WellRef inLocation, WellType inType) { mLocation = inLocation; mType = inType; } //-------------------------------------------------------------------------- public SimpleWell(XMLNode inXML) { inXML.verifyTagName(AutomationXML.WELL); mLocation = new WellRef(inXML.getAttributeValue(AutomationXML.REF_ATT)); if (inXML.hasAttribute(AutomationXML.TYPE_ATT)) { setType(WellType.valueOf(inXML.getAttributeValue(AutomationXML.TYPE_ATT))); } if (inXML.hasAttribute(AutomationXML.VOL_ATT)) { setVolume(new Quantity(inXML.getAttributeValue(AutomationXML.VOL_ATT))); } if (inXML.hasAttribute(AutomationXML.RAW_RESULT_ATT)) { setRawResult(Float.parseFloat(inXML.getAttributeValue(AutomationXML.RAW_RESULT_ATT))); } if (inXML.hasAttribute(AutomationXML.FLAGS_ATT)) { String[] stringValues = inXML.getAttributeValue(AutomationXML.FLAGS_ATT).split("[\\s,]+"); for (String stringValue : stringValues) { Flag flag = Flag.valueOf(stringValue); if (null == mFlags) { mFlags = EnumSet.of(flag); } else { mFlags.add(flag); } } } List sampleTags = inXML.getOptionalSubtagByName(AutomationXML.SAMPLE); if (CollectionUtil.hasValues(sampleTags)) { for (XMLNode sampleTag : sampleTags) { String sampleClassname = sampleTag.getAttributeValue(HfgBioXML.CLASS_ATT); if (! StringUtil.isSet(sampleClassname)) { throw new RuntimeException("No " + AutomationXML.CLASS_ATT + " specified on the Sample's XML tag!"); } S sample; if (sampleClassname.equals(String.class.getName())) { sample = (S) sampleTag.getUnescapedContent(); } else { try { Class clazz = Class.forName(sampleClassname); Constructor constructor = clazz.getConstructor(XMLNode.class); sample = (S) constructor.newInstance(sampleTag.getSubtags().get(0)); } catch (Exception e) { throw new RuntimeException("Error during Sample instantiation from its XML tag!", e); } } addSample(sample); } } } //########################################################################### // PUBLIC METHODS //########################################################################### //-------------------------------------------------------------------------- public XMLNode toXMLNode() { XMLNode node = new XMLTag(AutomationXML.WELL); node.setAttribute(AutomationXML.REF_ATT, getRef()); if (getType() != null) { node.setAttribute(AutomationXML.TYPE_ATT, getType()); } if (getVolume() != null) { node.setAttribute(AutomationXML.VOL_ATT, getVolume()); } if (getRawResult() != null) { node.setAttribute(AutomationXML.RAW_RESULT_ATT, getRawResult()); } if (mFlags != null) { node.setAttribute(AutomationXML.FLAGS_ATT, StringUtil.join(mFlags, ", ")); } if (CollectionUtil.hasValues(mSamples)) { for (S sample : mSamples) { XMLNode sampleTag = new XMLTag(AutomationXML.SAMPLE); sampleTag.setAttribute(AutomationXML.CLASS_ATT, sample.getClass().getName()); if (sample instanceof String) { sampleTag.setContent(sample.toString()); } else { sampleTag.addSubtag(((HfgXMLSerializable) sample).toXMLNode()); } sampleTag.addSubtag(sampleTag); node.addSubtag(sampleTag); } } return node; } //-------------------------------------------------------------------------- @Override public SimpleWell clone() { SimpleWell theClone; try { theClone = (SimpleWell) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } if (mSamples != null) { theClone.mSamples = new OrderedSet<>(mSamples); } return theClone; } //--------------------------------------------------------------------------- public WellRef getRef() { return mLocation; } //--------------------------------------------------------------------------- public SimpleWell setType(WellType inValue) { mType = inValue; return this; } //--------------------------------------------------------------------------- public WellType getType() { return mType; } //--------------------------------------------------------------------------- public SimpleWell setPlate(SimplePlate inValue) { mPlate = inValue; return this; } //--------------------------------------------------------------------------- public SimplePlate getPlate() { return mPlate; } //--------------------------------------------------------------------------- public SimpleWell addSample(T inValue) { return addSample(inValue, (Class) inValue.getClass()); } //--------------------------------------------------------------------------- public SimpleWell addSample(T inValue, Class inSampleClass) { if (null == mSamples) { mSamples = new OrderedSet<>(3); } mSamples.add((S)inValue); return this; } //--------------------------------------------------------------------------- public S[] getSamples(Class inClass) { return mSamples != null && mSamples.iterator().next().getClass().equals(inClass)? mSamples.toArray((S[]) Array.newInstance(mSamples.iterator().next().getClass(), 0)) : null; } //--------------------------------------------------------------------------- @Override public Comparable[] getSamples() { return mSamples != null ? mSamples.toArray((S[]) Array.newInstance(mSamples.iterator().next().getClass(), 0)) : null; } //--------------------------------------------------------------------------- public SimpleWell setVolume(Quantity inValue) { if (! inValue.getUnit().getQuantityType().equals(QuantityType.VOLUME)) { throw new InvalidValueException("The specified volume quantity " + StringUtil.singleQuote(inValue) + " isn't specified in volume units!"); } mVolume = inValue; return this; } //--------------------------------------------------------------------------- public SimpleWell addVolume(Quantity inValue) { if (inValue != null) { if (!inValue.getUnit().getQuantityType().equals(QuantityType.VOLUME)) { throw new InvalidValueException("The specified volume quantity " + StringUtil.singleQuote(inValue) + " isn't specified in volume units!"); } if (mVolume != null) { mVolume = mVolume.add(inValue); } else { mVolume = inValue; } } return this; } //--------------------------------------------------------------------------- public SimpleWell subtractVolume(Quantity inValue) { if (inValue != null) { if (!inValue.getUnit().getQuantityType().equals(QuantityType.VOLUME)) { throw new InvalidValueException("The specified volume quantity " + StringUtil.singleQuote(inValue) + " isn't specified in volume units!"); } if (null == mVolume) { throw new InvalidValueException("No initial volume in well " + getRef() + "! Can't subtract!"); } else { mVolume = mVolume.subtract(inValue); // TODO: Add check that the volume doesn't go below 0 } } return this; } //--------------------------------------------------------------------------- public Quantity getVolume() { return mVolume; } //--------------------------------------------------------------------------- /** Specifies the raw result value read for this well. @param inValue raw result as a float @return this Well to enable method chaining */ public SimpleWell setRawResult(Float inValue) { mRawResult = inValue; return this; } //--------------------------------------------------------------------------- /** Returns the raw result value read for this well. @return raw result as a float */ public Float getRawResult() { return mRawResult; } //--------------------------------------------------------------------------- public SimpleWell setSelected() { return setSelected(true); } //--------------------------------------------------------------------------- public SimpleWell setSelected(boolean inValue) { if (null == mFlags) { if (inValue) { mFlags = EnumSet.of(Flag.SELECTED); } } else if (inValue) { mFlags.add(Flag.SELECTED); } else { mFlags.remove(Flag.SELECTED); } return this; } //--------------------------------------------------------------------------- public boolean isSelected() { return (mFlags != null && mFlags.contains(Flag.SELECTED)); } }