/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * * Created on Jun 17, 2010 * Author: ap3 * */ package org.biojava.nbio.structure; import java.io.Serializable; import java.io.StringWriter; /** Everything that is needed to uniquely describe a residue position * * @author Andreas Prlic * */ public class ResidueNumber implements Serializable, Comparable<ResidueNumber> { private static final long serialVersionUID = 1773011704758536083L; private String chainName; private Character insCode; private Integer seqNum; public ResidueNumber() { } public ResidueNumber(ResidueNumber o) { this.chainName = o.chainName; this.insCode = o.insCode; this.seqNum = o.seqNum; } public ResidueNumber(String chainName, Integer residueNumber, Character insCode) { this.chainName = chainName; this.seqNum = residueNumber; this.insCode = insCode; } public String getChainName() { return chainName; } public void setChainName(String chainName) { this.chainName = chainName; } public Character getInsCode() { return insCode; } public void setInsCode(Character insCode) { this.insCode = insCode; } public Integer getSeqNum() { return seqNum; } public void setSeqNum(Integer seqNum) { this.seqNum = seqNum; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ResidueNumber other = (ResidueNumber) obj; if (chainName == null) { if (other.chainName != null) return false; } else if (!chainName.equals(other.chainName)) return false; if (insCode == null) { if (other.insCode != null) return false; } else if (!insCode.equals(other.insCode)) return false; if (seqNum == null) { if (other.seqNum != null) return false; } else if (!seqNum.equals(other.seqNum)) return false; return true; } /** * Check if the seqNum and insertion code are equivalent, * ignoring the chain * @param obj * @return */ public boolean equalsPositional(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ResidueNumber other = (ResidueNumber) obj; if (insCode == null) { if (other.insCode != null) return false; } else if (!insCode.equals(other.insCode)) return false; if (seqNum == null) { if (other.seqNum != null) return false; } else if (!seqNum.equals(other.seqNum)) return false; return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((chainName == null) ? 0 : chainName.hashCode()); result = prime * result + ((insCode == null) ? 0 : insCode.hashCode()); result = prime * result + ((seqNum == null) ? 0 : seqNum.hashCode()); return result; } /** * @return The residue number and insertion code as a string, eg "74A" * @see java.lang.Object#toString() */ @Override public String toString() { StringWriter writer = new StringWriter(); // if ( chainName != null){ // writer.append(chainName); // writer.append(":"); // } writer.append(String.valueOf(seqNum)); if ( insCode != null && ( insCode != ' ')) writer.append(insCode); return writer.toString(); } /** * @return The chain, number, and insertion code as a string, eg "B 74A" or "A 1 " */ public String toPDB() { String insCodeS ; if ( insCode != null) insCodeS = insCode+""; else insCodeS = " "; return String.format("%s%4d%-2s", chainName, seqNum, insCodeS); } /** Convert a string representation of a residue number to a residue number object. * The string representation can be a integer followed by a character. * * @param pdb_code * @return a ResidueNumber object, or null if the input was null */ public static ResidueNumber fromString(String pdb_code) { if(pdb_code == null) return null; ResidueNumber residueNumber = new ResidueNumber(); Integer resNum = null; String icode = null; try { resNum = Integer.parseInt(pdb_code); } catch ( NumberFormatException e){ // there is an insertion code.. // Split at any position that's either: // preceded by a digit and followed by a non-digit, or // preceded by a non-digit and followed by a digit. String[] spl = pdb_code.split("(?<=\\d)(?=\\D)|(?<=\\D)(?=\\d)"); if ( spl.length == 2){ resNum = Integer.parseInt(spl[0]); icode = spl[1]; } } residueNumber.setSeqNum(resNum); if ( icode == null) residueNumber.setInsCode(null); else if ( icode.length() > 0) residueNumber.setInsCode(icode.charAt(0)); return residueNumber; } /** * Compare residue numbers by chain, sequence number, and insertion code */ @Override public int compareTo(ResidueNumber other) { // chain id if (chainName != null && other.chainName != null) { if (!chainName.equals(other.chainName)) return chainName.compareTo(other.chainName); } if (chainName != null && other.chainName == null) { return 1; } else if (chainName == null && other.chainName != null) { return -1; } return compareToPositional(other); } /** * Compare residue numbers by sequence number and insertion code, * ignoring the chain * @param other * @return */ public int compareToPositional(ResidueNumber other) { // sequence number if (seqNum != null && other.seqNum != null) { if (!seqNum.equals(other.seqNum)) return seqNum.compareTo(other.seqNum); } if (seqNum != null && other.seqNum == null) { return 1; } else if (seqNum == null && other.seqNum != null) { return -1; } // insertion code if (insCode != null && other.insCode != null) { if (!insCode.equals(other.insCode)) return insCode.compareTo(other.insCode); } if (insCode != null && other.insCode == null) { return 1; } else if (insCode == null && other.insCode != null) { return -1; } return 0; } public String printFull() { final String chain = chainName==null? "" : chainName; return chain + "_" + toString(); } }