001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 * Created on Jun 17, 2010 021 * Author: ap3 022 * 023 */ 024 025package org.biojava.nbio.structure; 026 027import java.io.Serializable; 028import java.io.StringWriter; 029 030/** Everything that is needed to uniquely describe a residue position 031 * 032 * @author Andreas Prlic 033 * 034 */ 035public class ResidueNumber implements Serializable, Comparable<ResidueNumber> 036{ 037 038 private static final long serialVersionUID = 1773011704758536083L; 039 private String chainId; 040 private Character insCode; 041 private Integer seqNum; 042 043 public ResidueNumber() { 044 } 045 046 public ResidueNumber(ResidueNumber o) { 047 this.chainId = o.chainId; 048 this.insCode = o.insCode; 049 this.seqNum = o.seqNum; 050 } 051 052 public ResidueNumber(String chainId, Integer residueNumber, Character insCode) { 053 this.chainId = chainId; 054 this.seqNum = residueNumber; 055 this.insCode = insCode; 056 } 057 058 public String getChainId() 059 { 060 return chainId; 061 } 062 public void setChainId(String chainId) 063 { 064 this.chainId = chainId; 065 } 066 public Character getInsCode() 067 { 068 return insCode; 069 } 070 public void setInsCode(Character insCode) 071 { 072 this.insCode = insCode; 073 } 074 public Integer getSeqNum() 075 { 076 return seqNum; 077 } 078 public void setSeqNum(Integer seqNum) 079 { 080 this.seqNum = seqNum; 081 } 082 083 084 085 086 087 @Override 088 public boolean equals(Object obj) { 089 if (this == obj) 090 return true; 091 if (obj == null) 092 return false; 093 if (getClass() != obj.getClass()) 094 return false; 095 ResidueNumber other = (ResidueNumber) obj; 096 if (chainId == null) { 097 if (other.chainId != null) 098 return false; 099 } else if (!chainId.equals(other.chainId)) 100 return false; 101 if (insCode == null) { 102 if (other.insCode != null) 103 return false; 104 } else if (!insCode.equals(other.insCode)) 105 return false; 106 if (seqNum == null) { 107 if (other.seqNum != null) 108 return false; 109 } else if (!seqNum.equals(other.seqNum)) 110 return false; 111 112 return true; 113 } 114 115 @Override 116 public int hashCode() { 117 final int prime = 31; 118 int result = 1; 119 result = prime * result + ((chainId == null) ? 0 : chainId.hashCode()); 120 result = prime * result + ((insCode == null) ? 0 : insCode.hashCode()); 121 result = prime * result + ((seqNum == null) ? 0 : seqNum.hashCode()); 122 return result; 123 } 124 125 /** 126 * @return The residue number and insertion code as a string, eg "74A" 127 * @see java.lang.Object#toString() 128 */ 129 @Override 130 public String toString() { 131 132 StringWriter writer = new StringWriter(); 133 // if ( chainId != null){ 134 // writer.append(chainId); 135 // writer.append(":"); 136 // } 137 writer.append(String.valueOf(seqNum)); 138 if ( insCode != null && ( insCode != ' ')) 139 writer.append(insCode); 140 141 return writer.toString(); 142 } 143 144 /** 145 * @return The chain, number, and insertion code as a string, eg "B 74A" or "A 1 " 146 */ 147 public String toPDB() { 148 String insCodeS ; 149 if ( insCode != null) 150 insCodeS = insCode+""; 151 else insCodeS = " "; 152 return String.format("%s%4d%-2s", chainId, seqNum, insCodeS); 153 } 154 155 156 /** Convert a string representation of a residue number to a residue number object. 157 * The string representation can be a integer followed by a character. 158 * 159 * @param pdb_code 160 * @return a ResidueNumber object, or null if the input was null 161 */ 162 public static ResidueNumber fromString(String pdb_code) { 163 if(pdb_code == null) 164 return null; 165 166 ResidueNumber residueNumber = new ResidueNumber(); 167 Integer resNum = null; 168 String icode = null; 169 170 try { 171 resNum = Integer.parseInt(pdb_code); 172 } catch ( NumberFormatException e){ 173 // there is an insertion code.. 174 175 // Split at any position that's either: 176 // preceded by a digit and followed by a non-digit, or 177 // preceded by a non-digit and followed by a digit. 178 String[] spl = pdb_code.split("(?<=\\d)(?=\\D)|(?<=\\D)(?=\\d)"); 179 if ( spl.length == 2){ 180 resNum = Integer.parseInt(spl[0]); 181 icode = spl[1]; 182 } 183 184 } 185 186 residueNumber.setSeqNum(resNum); 187 if ( icode == null) 188 residueNumber.setInsCode(null); 189 else if ( icode.length() > 0) 190 residueNumber.setInsCode(icode.charAt(0)); 191 return residueNumber; 192 } 193 194 195 @Override 196 public int compareTo(ResidueNumber other) { 197 198 // chain id 199 if (chainId != null && other.chainId != null) { 200 if (!chainId.equals(other.chainId)) return chainId.compareTo(other.chainId); 201 } 202 if (chainId != null && other.chainId == null) { 203 return 1; 204 } else if (chainId == null && other.chainId != null) { 205 return -1; 206 } 207 208 // sequence number 209 if (seqNum != null && other.seqNum != null) { 210 if (!seqNum.equals(other.seqNum)) return seqNum.compareTo(other.seqNum); 211 } 212 if (seqNum != null && other.seqNum == null) { 213 return 1; 214 } else if (seqNum == null && other.seqNum != null) { 215 return -1; 216 } 217 218 // insertion code 219 if (insCode != null && other.insCode != null) { 220 if (!insCode.equals(other.insCode)) return insCode.compareTo(other.insCode); 221 } 222 if (insCode != null && other.insCode == null) { 223 return 1; 224 } else if (insCode == null && other.insCode != null) { 225 return -1; 226 } 227 228 return 0; 229 } 230 231 public String printFull() { 232 final String chain = chainId==null? "" : chainId; 233 return chain + "_" + toString(); 234 } 235 236}