Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.datamodel

File PDBEntry.java

 

Coverage histogram

../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

52
93
28
2
463
261
72
0.77
3.32
14
2.57

Classes

Class Line # Actions
PDBEntry 29 84 66 4
0.974522397.5%
PDBEntry.Type 47 9 6 4
0.7575%
 

Contributing tests

This file is covered by 40 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.datamodel;
22   
23    import jalview.util.CaseInsensitiveString;
24   
25    import java.util.Collections;
26    import java.util.Enumeration;
27    import java.util.Hashtable;
28   
 
29    public class PDBEntry
30    {
31   
32    /**
33    * constant for storing chain code in properties table
34    */
35    private static final String CHAIN_ID = "chain_code";
36   
37    private Hashtable<String, Object> properties;
38   
39    private static final int PDB_ID_LENGTH = 4;
40   
41    private String file;
42   
43    private String type;
44   
45    private String id;
46   
 
47    public enum Type
48    {
49    // TODO is FILE needed; if not is this enum needed, or can we
50    // use FileFormatI for PDB, MMCIF?
51    PDB("pdb", "pdb"), MMCIF("mmcif", "cif"), FILE("?", "?");
52   
53    /*
54    * file extension for cached structure file; must be one that
55    * is recognised by Chimera 'open' command
56    * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/filetypes.html
57    */
58    String ext;
59   
60    /*
61    * format specifier used in dbfetch request
62    * @see http://www.ebi.ac.uk/Tools/dbfetch/dbfetch/dbfetch.databases#pdb
63    */
64    String format;
65   
 
66  3 toggle private Type(String fmt, String ex)
67    {
68  3 format = fmt;
69  3 ext = ex;
70    }
71   
 
72  0 toggle public String getFormat()
73    {
74  0 return format;
75    }
76   
 
77  0 toggle public String getExtension()
78    {
79  0 return ext;
80    }
81   
82    /**
83    * case insensitive matching for Type enum
84    *
85    * @param value
86    * @return
87    */
 
88  103 toggle public static Type getType(String value)
89    {
90  103 for (Type t : Type.values())
91    {
92  111 if (t.toString().equalsIgnoreCase(value))
93    {
94  102 return t;
95    }
96    }
97  1 return null;
98    }
99   
100    /**
101    * case insensitive equivalence for strings resolving to PDBEntry type
102    *
103    * @param t
104    * @return
105    */
 
106  4 toggle public boolean matches(String t)
107    {
108  4 return (this.toString().equalsIgnoreCase(t));
109    }
110    }
111   
112    /**
113    * Answers true if obj is a PDBEntry with the same id and chain code (both
114    * ignoring case), file, type and properties
115    */
 
116  270 toggle @Override
117    public boolean equals(Object obj)
118    {
119  270 if (obj == null || !(obj instanceof PDBEntry))
120    {
121  2 return false;
122    }
123  268 if (obj == this)
124    {
125  11 return true;
126    }
127  257 PDBEntry o = (PDBEntry) obj;
128   
129    /*
130    * note that chain code is stored as a property wrapped by a
131    * CaseInsensitiveString, so we are in effect doing a
132    * case-insensitive comparison of chain codes
133    */
134  257 boolean idMatches = id == o.id
135    || (id != null && id.equalsIgnoreCase(o.id));
136  257 boolean fileMatches = file == o.file
137    || (file != null && file.equals(o.file));
138  257 boolean typeMatches = type == o.type
139    || (type != null && type.equals(o.type));
140  257 if (idMatches && fileMatches && typeMatches)
141    {
142  166 return properties == o.properties
143    || (properties != null && properties.equals(o.properties));
144    }
145  91 return false;
146    }
147   
148    /**
149    * Default constructor
150    */
 
151  375 toggle public PDBEntry()
152    {
153    }
154   
 
155  82 toggle public PDBEntry(String pdbId, String chain, PDBEntry.Type type,
156    String filePath)
157    {
158  82 init(pdbId, chain, type, filePath);
159    }
160   
161    /**
162    * @param pdbId
163    * @param chain
164    * @param entryType
165    * @param filePath
166    */
 
167  132 toggle void init(String pdbId, String chain, PDBEntry.Type entryType,
168    String filePath)
169    {
170  132 this.id = pdbId;
171  132 this.type = entryType == null ? null : entryType.toString();
172  132 this.file = filePath;
173  132 setChainCode(chain);
174    }
175   
176    /**
177    * Copy constructor.
178    *
179    * @param entry
180    */
 
181  6 toggle public PDBEntry(PDBEntry entry)
182    {
183  6 file = entry.file;
184  6 type = entry.type;
185  6 id = entry.id;
186  6 if (entry.properties != null)
187    {
188  6 properties = (Hashtable<String, Object>) entry.properties.clone();
189    }
190    }
191   
192    /**
193    * Make a PDBEntry from a DBRefEntry. The accession code is used for the PDB
194    * id, but if it is 5 characters in length, the last character is removed and
195    * set as the chain code instead.
196    *
197    * @param dbr
198    */
 
199  51 toggle public PDBEntry(DBRefEntry dbr)
200    {
201  51 if (!DBRefSource.PDB.equals(dbr.getSource()))
202    {
203  1 throw new IllegalArgumentException(
204    "Invalid source: " + dbr.getSource());
205    }
206   
207  50 String pdbId = dbr.getAccessionId();
208  50 String chainCode = null;
209  50 if (pdbId.length() == PDB_ID_LENGTH + 1)
210    {
211  17 char chain = pdbId.charAt(PDB_ID_LENGTH);
212  17 if (('a' <= chain && chain <= 'z') || ('A' <= chain && chain <= 'Z'))
213    {
214  15 pdbId = pdbId.substring(0, PDB_ID_LENGTH);
215  15 chainCode = String.valueOf(chain);
216    }
217    }
218  50 init(pdbId, chainCode, null, null);
219    }
220   
 
221  322 toggle public void setFile(String f)
222    {
223  322 this.file = f;
224    }
225   
 
226  1037 toggle public String getFile()
227    {
228  1037 return file;
229    }
230   
 
231  183 toggle public void setType(String t)
232    {
233  183 this.type = t;
234    }
235   
 
236  73 toggle public void setType(PDBEntry.Type type)
237    {
238  73 this.type = type == null ? null : type.toString();
239    }
240   
 
241  268 toggle public String getType()
242    {
243  268 return type;
244    }
245   
 
246  375 toggle public void setId(String id)
247    {
248  375 this.id = id;
249    }
250   
 
251  1000 toggle public String getId()
252    {
253  1000 return id;
254    }
255   
 
256  320 toggle public void setProperty(String key, Object value)
257    {
258  320 if (this.properties == null)
259    {
260  304 this.properties = new Hashtable<String, Object>();
261    }
262  320 properties.put(key, value);
263    }
264   
 
265  197 toggle public Object getProperty(String key)
266    {
267  197 return properties == null ? null : properties.get(key);
268    }
269   
270    /**
271    * Returns an enumeration of the keys of this object's properties (or an empty
272    * enumeration if it has no properties)
273    *
274    * @return
275    */
 
276  144 toggle public Enumeration<String> getProperties()
277    {
278  144 if (properties == null)
279    {
280  49 return Collections.emptyEnumeration();
281    }
282  95 return properties.keys();
283    }
284   
285    /**
286    *
287    * @return null or a string for associated chain IDs
288    */
 
289  300 toggle public String getChainCode()
290    {
291  300 return (properties == null || properties.get(CHAIN_ID) == null) ? null
292    : properties.get(CHAIN_ID).toString();
293    }
294   
295    /**
296    * Sets a non-case-sensitive property for the given chain code. Two PDBEntry
297    * objects which differ only in the case of their chain code are considered
298    * equal. This avoids duplication of objects in lists of PDB ids.
299    *
300    * @param chainCode
301    */
 
302  343 toggle public void setChainCode(String chainCode)
303    {
304  343 if (chainCode == null)
305    {
306  65 deleteProperty(CHAIN_ID);
307    }
308    else
309    {
310  278 setProperty(CHAIN_ID, new CaseInsensitiveString(chainCode));
311    }
312    }
313   
314    /**
315    * Deletes the property with the given key, and returns the deleted value (or
316    * null)
317    */
 
318  65 toggle Object deleteProperty(String key)
319    {
320  65 Object result = null;
321  65 if (properties != null)
322    {
323  1 result = properties.remove(key);
324    }
325  65 return result;
326    }
327   
 
328  26 toggle @Override
329    public String toString()
330    {
331  26 return id;
332    }
333   
334    /**
335    * Getter provided for Castor binding only. Application code should call
336    * getProperty() or getProperties() instead.
337    *
338    * @deprecated
339    * @see #getProperty(String)
340    * @see #getProperties()
341    * @see jalview.ws.dbsources.Uniprot#getUniprotEntries
342    * @return
343    */
 
344  28 toggle @Deprecated
345    public Hashtable<String, Object> getProps()
346    {
347  28 return properties;
348    }
349   
350    /**
351    * Setter provided for Castor binding only. Application code should call
352    * setProperty() instead.
353    *
354    * @deprecated
355    * @return
356    */
 
357  8 toggle @Deprecated
358    public void setProps(Hashtable<String, Object> props)
359    {
360  8 properties = props;
361    }
362   
363    /**
364    * Answers true if this object is either equivalent to, or can be 'improved'
365    * by, the given entry.
366    * <p>
367    * If newEntry has the same id (ignoring case), and doesn't have a conflicting
368    * file spec or chain code, then update this entry from its file and/or chain
369    * code.
370    *
371    * @param newEntry
372    * @return true if modifications were made
373    */
 
374  228 toggle public boolean updateFrom(PDBEntry newEntry)
375    {
376  228 if (this.equals(newEntry))
377    {
378  112 return true;
379    }
380   
381  116 String newId = newEntry.getId();
382  116 if (newId == null || getId() == null)
383    {
384  0 return false; // shouldn't happen
385    }
386   
387    /*
388    * id has to match (ignoring case)
389    */
390  116 if (!getId().equalsIgnoreCase(newId))
391    {
392  24 return false;
393    }
394   
395    /*
396    * Don't update if associated with different structure files
397    */
398  92 String newFile = newEntry.getFile();
399  92 if (newFile != null && getFile() != null && !newFile.equals(getFile()))
400    {
401  3 return false;
402    }
403   
404    /*
405    * Don't update if associated with different chains (ignoring case)
406    */
407  89 String newChain = newEntry.getChainCode();
408  89 if (newChain != null && newChain.length() > 0 && getChainCode() != null
409    && getChainCode().length() > 0
410    && !getChainCode().equalsIgnoreCase(newChain))
411    {
412  8 return false;
413    }
414   
415    /*
416    * set file path if not already set
417    */
418  81 String newType = newEntry.getType();
419  81 if (getFile() == null && newFile != null)
420    {
421  3 setFile(newFile);
422  3 setType(newType);
423    }
424   
425    /*
426    * set file type if new entry has it and we don't
427    * (for the case where file was not updated)
428    */
429  81 if (getType() == null && newType != null)
430    {
431  11 setType(newType);
432    }
433   
434    /*
435    * set chain if not already set (we excluded differing
436    * chains earlier) (ignoring case change only)
437    */
438  81 if (newChain != null && newChain.length() > 0
439    && !newChain.equalsIgnoreCase(getChainCode()))
440    {
441  25 setChainCode(newChain);
442    }
443   
444    /*
445    * copy any new or modified properties
446    */
447  81 Enumeration<String> newProps = newEntry.getProperties();
448  131 while (newProps.hasMoreElements())
449    {
450    /*
451    * copy properties unless value matches; this defends against changing
452    * the case of chain_code which is wrapped in a CaseInsensitiveString
453    */
454  50 String key = newProps.nextElement();
455  50 Object value = newEntry.getProperty(key);
456  50 if (!value.equals(getProperty(key)))
457    {
458  11 setProperty(key, value);
459    }
460    }
461  81 return true;
462    }
463    }