Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.io

File ModellerDescription.java

 

Coverage histogram

../../img/srcFileCovDistChart2.png
50% of files have more coverage

Code metrics

76
127
16
2
432
315
69
0.54
7.94
8
4.31

Classes

Class Line # Actions
ModellerDescription 30 123 67
0.1455399114.6%
ModellerDescription.resCode 79 4 2
0.00%
 

Contributing tests

This file is covered by 1 test. .

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.io;
22   
23    import jalview.datamodel.DBRefEntry;
24    import jalview.datamodel.SequenceI;
25   
26    import java.util.List;
27   
28    import com.stevesoft.pat.Regex;
29   
 
30    public class ModellerDescription
31    {
32    /**
33    * Translates between a String containing a set of colon-separated values on a
34    * single line, and sequence start/end and other properties. See PIRFile IO
35    * for its use.
36    */
37    final String[] seqTypes = { "sequence", "structure", "structureX",
38    "structureN" };
39   
40    final String[] Fields = { "objectType", "objectId", "startField",
41    "startCode", "endField", "endCode", "description1", "description2",
42    "resolutionField", "tailField" };
43   
44    final int TYPE = 0;
45   
46    final int LOCALID = 1;
47   
48    final int START = 2;
49   
50    final int START_CHAIN = 3;
51   
52    final int END = 4;
53   
54    final int END_CHAIN = 5;
55   
56    final int DESCRIPTION1 = 6;
57   
58    final int DESCRIPTION2 = 7;
59   
60    final int RESOLUTION = 8;
61   
62    final int TAIL = 9;
63   
64    /**
65    * 0 is free text or empty 1 is something that parses to an integer, or \@
66    */
67    final int Types[] = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 };
68   
69    final char Padding[] = { ' ', ' ', ' ', '.', ' ', '.', '.', '.', '.',
70    '.' };
71   
72    java.util.Hashtable fields = new java.util.Hashtable();
73   
 
74  0 toggle ModellerDescription()
75    {
76  0 fields.put(Fields[TAIL], "");
77    }
78   
 
79    class resCode
80    {
81    Integer val;
82   
83    String field;
84   
 
85  0 toggle resCode(String f, Integer v)
86    {
87  0 val = v;
88  0 field = f;
89    }
90   
 
91  0 toggle resCode(int v)
92    {
93  0 val = Integer.valueOf(v);
94  0 field = val.toString();
95    }
96    };
97   
 
98  0 toggle private resCode validResidueCode(String field)
99    {
100  0 Integer val = null;
101  0 Regex r = new Regex(
102    "\\s*((([-0-9]+).?)|FIRST|LAST|@)");
103   
104  0 if (!r.search(field))
105    {
106  0 return null; // invalid
107    }
108  0 String value = r.stringMatched(3);
109  0 if (value == null)
110    {
111  0 value = r.stringMatched(1);
112    }
113    // jalview.bin.Cache.log.debug("from '" + field + "' matched '" + value +
114    // "'");
115  0 try
116    {
117  0 val = Integer.valueOf(value);
118  0 return new resCode(field, val); // successful numeric extraction
119    } catch (Exception e)
120    {
121    }
122  0 return new resCode(field, null);
123    }
124   
 
125  15 toggle private java.util.Hashtable parseDescription(String desc)
126    {
127  15 java.util.Hashtable fields = new java.util.Hashtable();
128  15 java.util.StringTokenizer st = new java.util.StringTokenizer(desc, ":",
129    true);
130   
131  15 String field;
132  15 int type = -1;
133  15 if (st.countTokens() > 0)
134    {
135    // parse colon-fields
136  15 int i = 0;
137  15 field = st.nextToken(":");
138  15 do
139    {
140  60 if (seqTypes[i].equalsIgnoreCase(field))
141    {
142  0 break;
143    }
144  60 } while (++i < seqTypes.length);
145   
146  15 if (i < seqTypes.length)
147    {
148  0 st.nextToken(); // skip ':'
149    // valid seqType for modeller
150  0 type = i;
151  0 i = 1; // continue parsing fields
152  0 while (i < TAIL && st.hasMoreTokens())
153    {
154  0 if ((field = st.nextToken(":")) != null)
155    {
156  0 if (!field.equals(":"))
157    {
158    // validate residue field value
159  0 if (Types[i] == 1)
160    {
161  0 resCode val = validResidueCode(field);
162  0 if (val != null)
163    {
164  0 fields.put(new String(Fields[i] + "num"), val);
165    }
166    else
167    {
168    // jalview.bin.Cache.log.debug(
169    // "Ignoring non-Modeller description: invalid integer-like
170    // field '" + field + "'");
171  0 type = -1; /* invalid field! - throw the FieldSet away */
172    }
173  0 ;
174    }
175  0 fields.put(Fields[i++], field);
176  0 if (st.hasMoreTokens())
177    {
178  0 st.nextToken(); // skip token sep.
179    }
180    }
181    else
182    {
183  0 i++;
184    }
185    }
186    }
187  0 if (i == TAIL)
188    {
189    // slurp remaining fields
190  0 while (st.hasMoreTokens())
191    {
192  0 String tl = st.nextToken(":");
193  0 field += tl.equals(":") ? tl : (":" + tl);
194    }
195  0 fields.put(Fields[TAIL], field);
196    }
197    }
198    }
199  15 if (type == -1)
200    {
201    // object is not a proper ModellerPIR object
202  15 fields = new java.util.Hashtable();
203  15 fields.put(Fields[TAIL], new String(desc));
204    }
205    else
206    {
207  0 fields.put(Fields[TYPE], seqTypes[type]);
208    }
209  15 return fields;
210    }
211   
 
212  15 toggle ModellerDescription(String desc)
213    {
214  15 if (desc == null)
215    {
216  0 desc = "";
217    }
218  15 fields = parseDescription(desc);
219    }
220   
 
221  0 toggle void setStartCode(int v)
222    {
223  0 resCode r;
224  0 fields.put(Fields[START] + "num", r = new resCode(v));
225  0 fields.put(Fields[START], r.field);
226    }
227   
 
228  0 toggle void setEndCode(int v)
229    {
230  0 resCode r;
231  0 fields.put(Fields[END] + "num", r = new resCode(v));
232  0 fields.put(Fields[END], r.field);
233    }
234   
235    /**
236    * make a possibly updated modeller field line for the sequence object
237    *
238    * @param seq
239    * SequenceI
240    */
 
241  0 toggle ModellerDescription(SequenceI seq)
242    {
243   
244  0 if (seq.getDescription() != null)
245    {
246  0 fields = parseDescription(seq.getDescription());
247    }
248   
249  0 if (isModellerFieldset())
250    {
251    // Set start and end before we update the type (in the case of a
252    // synthesized field set)
253  0 if (getStartCode() == null || (getStartNum() != seq.getStart()
254    && getStartCode().val != null))
255    {
256    // unset or user updated sequence start position
257  0 setStartCode(seq.getStart());
258    }
259   
260  0 if (getEndCode() == null || (getEndNum() != seq.getEnd()
261    && getStartCode() != null && getStartCode().val != null))
262    {
263  0 setEndCode(seq.getEnd());
264    }
265    }
266    else
267    {
268    // synthesize fields
269  0 setStartCode(seq.getStart());
270  0 setEndCode(seq.getEnd());
271  0 fields.put(Fields[LOCALID], seq.getName()); // this may be overwritten
272    // below...
273    // type - decide based on evidence of PDB database references - this also
274    // sets the local reference field
275  0 int t = 0; // sequence
276  0 if (seq.getDatasetSequence() != null
277    && seq.getDatasetSequence().getDBRefs() != null)
278    {
279  0 List<DBRefEntry> dbr = seq.getDatasetSequence().getDBRefs();
280  0 for (int i = 0, ni = dbr.size(); i < ni; i++)
281    {
282  0 DBRefEntry dbri = dbr.get(i);
283  0 if (dbri != null)
284    {
285    // JBPNote PDB dbRefEntry needs properties to propagate onto
286    // ModellerField
287    // JBPNote Need to get info from the user about whether the sequence
288    // is the one being modelled, or if it is a template.
289  0 if (dbri.getSource()
290    .equals(jalview.datamodel.DBRefSource.PDB))
291    {
292  0 fields.put(Fields[LOCALID], dbri.getAccessionId());
293  0 t = 2;
294  0 break;
295    }
296    }
297    }
298    }
299  0 fields.put(Fields[TYPE], seqTypes[t]);
300    }
301   
302    }
303   
304    /**
305    * Indicate if fields parsed to a modeller-like colon-separated value line
306    *
307    * @return boolean
308    */
 
309  15 toggle boolean isModellerFieldset()
310    {
311  15 return (fields.containsKey(Fields[TYPE]));
312    }
313   
 
314  0 toggle String getDescriptionLine()
315    {
316  0 String desc = "";
317  0 int lastfield = Fields.length - 1;
318   
319  0 if (isModellerFieldset())
320    {
321  0 String value;
322    // try to write a minimal modeller field set, so..
323   
324    // find the last valid field in the entry
325   
326  0 for (; lastfield > 6; lastfield--)
327    {
328  0 if (fields.containsKey(Fields[lastfield]))
329    {
330  0 break;
331    }
332    }
333   
334  0 for (int i = 0; i < lastfield; i++)
335    {
336  0 value = (String) fields.get(Fields[i]);
337  0 if (value != null && value.length() > 0)
338    {
339  0 desc += ((String) fields.get(Fields[i])) + ":";
340    }
341    else
342    {
343  0 desc += Padding[i] + ":";
344    }
345    }
346    }
347    // just return the last field if no others were defined.
348  0 if (fields.containsKey(Fields[lastfield]))
349    {
350  0 desc += (String) fields.get(Fields[lastfield]);
351    }
352    else
353    {
354  0 desc += ".";
355    }
356  0 return desc;
357    }
358   
 
359  0 toggle int getStartNum()
360    {
361  0 int start = 0;
362  0 resCode val = getStartCode();
363  0 if (val != null && val.val != null)
364    {
365  0 return val.val.intValue();
366    }
367  0 return start;
368    }
369   
 
370  0 toggle resCode getStartCode()
371    {
372  0 if (isModellerFieldset() && fields.containsKey(Fields[START] + "num"))
373    {
374  0 return (resCode) fields.get(Fields[START] + "num");
375    }
376  0 return null;
377    }
378   
 
379  0 toggle resCode getEndCode()
380    {
381  0 if (isModellerFieldset() && fields.containsKey(Fields[END] + "num"))
382    {
383  0 return (resCode) fields.get(Fields[END] + "num");
384    }
385  0 return null;
386    }
387   
 
388  0 toggle int getEndNum()
389    {
390  0 int end = 0;
391  0 resCode val = getEndCode();
392  0 if (val != null && val.val != null)
393    {
394  0 return val.val.intValue();
395    }
396  0 return end;
397    }
398   
399    /**
400    * returns true if sequence object was modifed with a valid modellerField set
401    *
402    * @param newSeq
403    * SequenceI
404    * @return boolean
405    */
 
406  15 toggle boolean updateSequenceI(SequenceI newSeq)
407    {
408  15 if (isModellerFieldset())
409    {
410  0 resCode rc = getStartCode();
411  0 if (rc != null && rc.val != null)
412    {
413  0 newSeq.setStart(getStartNum());
414    }
415    else
416    {
417  0 newSeq.setStart(1);
418    }
419  0 rc = getEndCode();
420  0 if (rc != null && rc.val != null)
421    {
422  0 newSeq.setEnd(getEndNum());
423    }
424    else
425    {
426  0 newSeq.setEnd(newSeq.getStart() + newSeq.getLength());
427    }
428  0 return true;
429    }
430  15 return false;
431    }
432    }