001package com.hfg.bio.seq; 002 003import com.hfg.bio.AminoAcid; 004import com.hfg.chem.Element; 005import com.hfg.bio.HfgBioXML; 006import com.hfg.chem.Molecule; 007import com.hfg.util.CompareUtil; 008import com.hfg.xml.XMLNode; 009import com.hfg.xml.XMLTag; 010 011import java.util.Map; 012 013//------------------------------------------------------------------------------ 014/** 015 * Biological protein sequence crosslink. 016 * 017 * @author J. Alex Taylor, hairyfatguy.com 018 */ 019//------------------------------------------------------------------------------ 020// com.hfg XML/HTML Coding Library 021// 022// This library is free software; you can redistribute it and/or 023// modify it under the terms of the GNU Lesser General Public 024// License as published by the Free Software Foundation; either 025// version 2.1 of the License, or (at your option) any later version. 026// 027// This library is distributed in the hope that it will be useful, 028// but WITHOUT ANY WARRANTY; without even the implied warranty of 029// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 030// Lesser General Public License for more details. 031// 032// You should have received a copy of the GNU Lesser General Public 033// License along with this library; if not, write to the Free Software 034// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 035// 036// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 037// jataylor@hairyfatguy.com 038//------------------------------------------------------------------------------ 039 040 041public class ProteinXLink extends Molecule implements Cloneable 042{ 043 044 private ProteinXLinkType mType; 045 private Protein mDonorChain; 046 private String mDonorChainId; 047 private Integer mDonorPosition; 048 private Protein mAcceptorChain; 049 private String mAcceptorChainId; 050 private Integer mAcceptorPosition; 051 052 private char mDonorResidue; 053 private char mAcceptorResidue; 054 055 private Protein mParentProtein; 056 057 //########################################################################## 058 // CONSTRUCTORS 059 //########################################################################## 060 061 //-------------------------------------------------------------------------- 062 public ProteinXLink(ProteinXLinkType inType, Protein inDonorChain, int inDonorPosition, Protein inAcceptorChain, int inAcceptorPosition) 063 { 064 mType = inType; 065 mDonorChain = inDonorChain; 066 mDonorChainId = inDonorChain.getID(); 067 mDonorPosition = inDonorPosition; 068 mAcceptorChain = inAcceptorChain; 069 mAcceptorChainId = inAcceptorChain.getID(); 070 mAcceptorPosition = inAcceptorPosition; 071 072 mDonorResidue = inDonorChain.residueAt(inDonorPosition); 073 mAcceptorResidue = inAcceptorChain.residueAt(inAcceptorPosition); 074 075 validate(); 076 } 077 078 //-------------------------------------------------------------------------- 079 public ProteinXLink(XMLNode inXML) 080 { 081 if (! inXML.getTagName().equals(HfgBioXML.XLINK_TAG)) 082 { 083 throw new RuntimeException("Cannot construct an " + this.getClass().getSimpleName() + " from a " + inXML.getTagName() + " tag!"); 084 } 085 086 mType = new ProteinXLinkType(inXML.getRequiredSubtagByName(HfgBioXML.XLINK_TYPE_TAG)); 087 088 XMLNode donorTag = inXML.getRequiredSubtagByName(HfgBioXML.DONOR_TAG); 089 mDonorChainId = donorTag.getAttributeValue(HfgBioXML.CHAIN_ID_ATT); 090 mDonorPosition = Integer.parseInt(donorTag.getAttributeValue(HfgBioXML.RESIDUE_ATT)); 091 092 XMLNode acceptorTag = inXML.getRequiredSubtagByName(HfgBioXML.ACCEPTOR_TAG); 093 mAcceptorChainId = acceptorTag.getAttributeValue(HfgBioXML.CHAIN_ID_ATT); 094 mAcceptorPosition = Integer.parseInt(acceptorTag.getAttributeValue(HfgBioXML.RESIDUE_ATT)); 095 } 096 097 //########################################################################## 098 // PUBLIC METHODS 099 //########################################################################## 100 101 //--------------------------------------------------------------------------- 102 @Override 103 public ProteinXLink clone() 104 { 105 ProteinXLink copy = (ProteinXLink) super.clone(); 106 107 return copy; 108 } 109 110 //-------------------------------------------------------------------------- 111 public ProteinXLinkChainLinkage getChainLinkage() 112 { 113 return (0 == CompareUtil.compare(getDonorChainId(), getAcceptorChainId()) ? ProteinXLinkChainLinkage.INTRACHAIN : ProteinXLinkChainLinkage.INTERCHAIN); 114 } 115 116 //-------------------------------------------------------------------------- 117 public ProteinXLinkType getType() 118 { 119 return mType; 120 } 121 122 123 //-------------------------------------------------------------------------- 124 public String getDonorChainId() 125 { 126 return mDonorChainId; 127 } 128 129 //-------------------------------------------------------------------------- 130 protected ProteinXLink setDonorChainId(String inValue) 131 { 132 mDonorChainId = inValue; 133 return this; 134 } 135 136 137 //-------------------------------------------------------------------------- 138 public int getDonorPosition() 139 { 140 return mDonorPosition; 141 } 142 143 144 //-------------------------------------------------------------------------- 145 public String getAcceptorChainId() 146 { 147 return mAcceptorChainId; 148 } 149 150 //-------------------------------------------------------------------------- 151 protected ProteinXLink setAcceptorChainId(String inValue) 152 { 153 mAcceptorChainId = inValue; 154 return this; 155 } 156 157 158 //-------------------------------------------------------------------------- 159 public int getAcceptorPosition() 160 { 161 return mAcceptorPosition; 162 } 163 164 //-------------------------------------------------------------------------- 165 public String toString() 166 { 167 return mType.name() + ": " + (mDonorChainId != null ? mDonorChainId : "") + " " + mDonorResidue + mDonorPosition + " --> " 168 + (mAcceptorChainId != null ? mAcceptorChainId : "") + " " + mAcceptorResidue + mAcceptorPosition; 169 } 170 171 //-------------------------------------------------------------------------- 172 public XMLNode toXMLNode() 173 { 174 XMLNode node = new XMLTag(HfgBioXML.XLINK_TAG); 175 176 node.addSubtag(mType.toXMLNode()); 177 178 XMLNode donorTag = new XMLTag(HfgBioXML.DONOR_TAG); 179 node.addSubtag(donorTag); 180 donorTag.setAttribute(HfgBioXML.CHAIN_ID_ATT, mDonorChainId); 181 donorTag.setAttribute(HfgBioXML.RESIDUE_ATT, mDonorPosition); 182 183 XMLNode acceptorTag = new XMLTag(HfgBioXML.ACCEPTOR_TAG); 184 node.addSubtag(acceptorTag); 185 acceptorTag.setAttribute(HfgBioXML.CHAIN_ID_ATT, mAcceptorChainId); 186 acceptorTag.setAttribute(HfgBioXML.RESIDUE_ATT, mAcceptorPosition); 187 188 189 return node; 190 } 191 192 //-------------------------------------------------------------------------- 193 /** 194 Returns an unmodifiable copy of the elemental composition Map. The keys are 195 Element objects and the values are Floats. Why Floats instead of Integers you 196 ask? Because some amino acid codes such as B and Z are ambiguous averages. 197 @return an elemental composition map 198 */ 199 public Map<Element, Float> getElementalComposition() 200 { 201 return mType.getElementalComposition(); 202 } 203 204 //-------------------------------------------------------------------------- 205 public Double getMonoisotopicMass() 206 { 207 return mType.getMonoisotopicMass(); 208 } 209 210 //-------------------------------------------------------------------------- 211 public Double getAverageMass() 212 { 213 return mType.getAverageMass(); 214 } 215 216 //-------------------------------------------------------------------------- 217 public Double getOrganicAverageMass() 218 { 219 return mType.getOrganicAverageMass(); 220 } 221 222 //-------------------------------------------------------------------------- 223 /** 224 Sets the protein container to which this x-link belongs. 225 @param inParentProtein the protein to which this x-link belongs 226 */ 227 protected void setParentProtein(Protein inParentProtein) 228 { 229 if (inParentProtein != null) 230 { 231 // Validate that the donor chain is present in the parent protein. 232 if (mDonorChain != null) 233 { 234 if (inParentProtein != mDonorChain 235 && null == inParentProtein.getChain(mDonorChainId)) 236 { 237 throw new RuntimeException("Donor chain '" + mDonorChainId + "' is not present in this Protein!"); 238 } 239 } 240 else 241 { 242 mDonorChain = inParentProtein.getChain(mDonorChainId); 243 if (null == mDonorChain) 244 { 245 throw new RuntimeException("Donor chain '" + mDonorChainId + "' is not present in this Protein!"); 246 } 247 } 248 249 // Validate that the acceptor chain is present in the parent protein. 250 if (mAcceptorChain != null) 251 { 252 if (inParentProtein != mAcceptorChain 253 && null == inParentProtein.getChain(mAcceptorChainId)) 254 { 255 throw new RuntimeException("Acceptor chain '" + mAcceptorChainId + "' is not present in this Protein!"); 256 } 257 } 258 else 259 { 260 mAcceptorChain = inParentProtein.getChain(mAcceptorChainId); 261 if (null == mAcceptorChain) 262 { 263 throw new RuntimeException("Acceptor chain '" + mAcceptorChainId + "' is not present in this Protein!"); 264 } 265 } 266 267 // Be sure the donor residue is not already occupied 268 // TODO 269 270 // Be sure the acceptor residue is not already occupied 271 // TODO 272 } 273 274 mParentProtein = inParentProtein; 275 } 276 277 //-------------------------------------------------------------------------- 278 protected void validate() 279 { 280 AminoAcid donor = mDonorChain.aminoAcidAt(mDonorPosition); 281 AminoAcid acceptor = mAcceptorChain.aminoAcidAt(mAcceptorPosition); 282 if (! mType.isAcceptableSite(donor, acceptor)) 283 { 284 throw new RuntimeException("Not a valid X-Link!\n" + this); 285 } 286 } 287 288 //-------------------------------------------------------------------------- 289 @Override 290 public boolean equals(Object inObj) 291 { 292 return inObj instanceof ProteinXLink ? compareTo(inObj) == 0 : false; 293 } 294 295 //-------------------------------------------------------------------------- 296 @Override 297 public int hashCode() 298 { 299 int hashCode = getType().hashCode(); 300 if (mDonorChainId != null) hashCode += mDonorChainId.hashCode(); 301 hashCode += mDonorPosition.hashCode(); 302 if (mAcceptorChainId != null) hashCode += mAcceptorChainId.hashCode(); 303 hashCode += mAcceptorPosition.hashCode(); 304 305 return hashCode; 306 } 307 308 //-------------------------------------------------------------------------- 309 public int compareTo(Object inObj) 310 { 311 int result = -1; 312 313 if (inObj != null) 314 { 315 if (inObj instanceof ProteinXLink) 316 { 317 ProteinXLink xlink2 = (ProteinXLink) inObj; 318 319 result = getDonorChainId().compareTo(xlink2.getDonorChainId()); 320 if (0 == result) 321 { 322 result = mDonorPosition.compareTo(xlink2.mDonorPosition); 323 324 if (0 == result) 325 { 326 result = getAcceptorChainId().compareTo(xlink2.getAcceptorChainId()); 327 if (0 == result) 328 { 329 result = mAcceptorPosition.compareTo(xlink2.mAcceptorPosition); 330 } 331 } 332 } 333 } 334 else 335 { 336 result = CompareUtil.compare(hashCode(), inObj.hashCode()); 337 } 338 } 339 340 return result; 341 } 342 343}