-package jalview.io;\r
-\r
-import jalview.datamodel.SequenceI;\r
-import java.util.Vector;\r
-public class ModellerDescription\r
-{\r
- /**\r
- * Translates between a String containing a set of colon-separated values\r
- * on a single line, and sequence start/end and other properties.\r
- * See PIRFile IO for its use.\r
- */\r
- final String[] seqTypes =\r
- {\r
- "sequence", "structure", "structureX", "structureN"};\r
- final String[] Fields =\r
- {\r
- "objectType", "objectId",\r
- "startField", "startCode",\r
- "endField", "endCode",\r
- "description1", "description2",\r
- "resolutionField", "tailField"};\r
- final int TYPE = 0;\r
- final int LOCALID = 1;\r
- final int START = 2;\r
- final int START_CHAIN = 3;\r
- final int END = 4;\r
- final int END_CHAIN = 5;\r
- final int DESCRIPTION1 = 6;\r
- final int DESCRIPTION2 = 7;\r
- final int RESOLUTION = 8;\r
- final int TAIL = 9;\r
-\r
- /**\r
- * 0 is free text or empty\r
- * 1 is something that parses to an integer, or \@\r
- */\r
- final int Types[] =\r
- {\r
- 0, 0, 1, 0, 1, 0, 0, 0, 0, 0\r
- };\r
- final char Padding[] =\r
- {\r
- ' ', ' ', ' ', '.', ' ', '.', '.', '.', '.', '.'\r
- };\r
-\r
- java.util.Hashtable fields = new java.util.Hashtable();\r
- ModellerDescription()\r
- {\r
- fields.put(Fields[TAIL], "");\r
- }\r
-\r
- class resCode\r
- {\r
- Integer val;\r
- String field;\r
- resCode(String f, Integer v)\r
- {\r
- val = v;\r
- field = f;\r
- }\r
-\r
- resCode(int v)\r
- {\r
- val = new Integer(v);\r
- field = val.toString();\r
- }\r
- };\r
-\r
- private resCode validResidueCode(String field)\r
- {\r
- Integer val = null;\r
- com.stevesoft.pat.Regex r = new com.stevesoft.pat.Regex("\\s*((([-0-9]+).?)|FIRST|LAST|@)");\r
-\r
- if (!r.search(field))\r
- {\r
- return null; // invalid\r
- }\r
- String value = r.stringMatched(3);\r
- if (value == null)\r
- {\r
- value = r.stringMatched(1);\r
- }\r
- // jalview.bin.Cache.log.debug("from '" + field + "' matched '" + value +\r
- // "'");\r
- try\r
- {\r
- val = Integer.valueOf(value);\r
- return new resCode(field, val); // successful numeric extraction\r
- }\r
- catch (Exception e)\r
- {\r
- }\r
- return new resCode(field, null);\r
- }\r
-\r
- private java.util.Hashtable parseDescription(String desc)\r
- {\r
- java.util.Hashtable fields = new java.util.Hashtable();\r
- java.util.StringTokenizer st = new java.util.StringTokenizer(desc, ":");\r
- String field;\r
- int type = -1;\r
- if (st.countTokens() > 0)\r
- {\r
- // parse colon-fields\r
- int i = 0;\r
- field = st.nextToken(":");\r
- do\r
- {\r
- if (seqTypes[i].equalsIgnoreCase(field) )\r
- {\r
- break;\r
- }\r
- }\r
- while (++i < seqTypes.length);\r
-\r
- if (i < seqTypes.length)\r
- {\r
- // valid seqType for modeller\r
- type = i;\r
- i = 1; // continue parsing fields\r
- while (i < TAIL && st.hasMoreTokens())\r
- {\r
- if ( (field = st.nextToken(":")) != null)\r
- {\r
- // validate residue field value\r
- if (Types[i] == 1)\r
- {\r
- resCode val = validResidueCode(field);\r
- if (val != null)\r
- {\r
- fields.put(new String(Fields[i] + "num"), val);\r
- }\r
- else\r
- {\r
- // jalview.bin.Cache.log.debug(\r
- // "Ignoring non-Modeller description: invalid integer-like field '" + field + "'");\r
- type = -1; /* invalid field! - throw the FieldSet away */\r
- }\r
- ;\r
- }\r
- fields.put(Fields[i++], field);\r
- }\r
- }\r
- if (i == TAIL)\r
- {\r
- // slurp remaining fields\r
- while (st.hasMoreTokens())\r
- {\r
- field += ":" + st.nextToken(":");\r
- }\r
- fields.put(Fields[TAIL], field);\r
- }\r
- }\r
- }\r
- if (type == -1)\r
- {\r
- // object is not a proper ModellerPIR object\r
- fields = new java.util.Hashtable();\r
- fields.put(Fields[TAIL], new String(desc));\r
- }\r
- else\r
- {\r
- fields.put(Fields[TYPE], seqTypes[type]);\r
- }\r
- return fields;\r
- }\r
-\r
- ModellerDescription(String desc)\r
- {\r
- if (desc == null)\r
- {\r
- desc = "";\r
- }\r
- fields = parseDescription(desc);\r
- }\r
-\r
- void setStartCode(int v)\r
- {\r
- resCode r;\r
- fields.put(Fields[START] + "num", r = new resCode(v));\r
- fields.put(Fields[START], r.field);\r
- }\r
-\r
- void setEndCode(int v)\r
- {\r
- resCode r;\r
- fields.put(Fields[END] + "num", r = new resCode(v));\r
- fields.put(Fields[END], r.field);\r
- }\r
-\r
- /**\r
- * make a possibly updated modeller field line for the sequence object\r
- * @param seq SequenceI\r
- */\r
- ModellerDescription(SequenceI seq)\r
- {\r
-\r
- if (seq.getDescription() != null)\r
- {\r
- fields = parseDescription(seq.getDescription());\r
- }\r
-\r
- if (isModellerFieldset())\r
- {\r
- // Set start and end before we update the type (in the case of a synthesized field set)\r
- if (getStartNum() != seq.getStart() && getStartCode().val != null)\r
- {\r
- setStartCode(seq.getStart());\r
- }\r
-\r
- if (getEndNum() != seq.getEnd() && getStartCode().val != null)\r
- {\r
- setEndCode(seq.getEnd());\r
- }\r
- }\r
- else\r
- {\r
- // synthesize fields\r
- setStartCode(seq.getStart());\r
- setEndCode(seq.getEnd());\r
- fields.put(Fields[LOCALID], seq.getName()); // this may be overwritten below...\r
- // type - decide based on evidence of PDB database references - this also sets the local reference field\r
- int t = 0; // sequence\r
- if (seq.getDatasetSequence() != null &&\r
- seq.getDatasetSequence().getDBRef() != null)\r
- {\r
- jalview.datamodel.DBRefEntry [] dbr = seq.getDatasetSequence().getDBRef();\r
- int i, j;\r
- for (i = 0, j = dbr.length; i < j; i++)\r
- {\r
- if (dbr[i] != null)\r
- {\r
- // JBPNote PDB dbRefEntry needs properties to propagate onto ModellerField\r
- // JBPNote Need to get info from the user about whether the sequence is the one being modelled, or if it is a template.\r
- if (dbr[i].getSource().equals(jalview.datamodel.DBRefSource.PDB))\r
- {\r
- fields.put(Fields[LOCALID], dbr[i].getAccessionId());\r
- t = 2;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- fields.put(Fields[TYPE], seqTypes[t]);\r
- }\r
-\r
- }\r
-\r
- /**\r
- * Indicate if fields parsed to a modeller-like colon-separated value line\r
- * @return boolean\r
- */\r
- boolean isModellerFieldset()\r
- {\r
- return (fields.containsKey(Fields[TYPE]));\r
- }\r
-\r
- String getDescriptionLine()\r
- {\r
- String desc = "";\r
- int lastfield = Fields.length - 1;\r
-\r
- if (isModellerFieldset())\r
- {\r
- String value;\r
- // try to write a minimal modeller field set, so..\r
-\r
- // find the last valid field in the entry\r
-\r
- for (; lastfield > 6; lastfield--)\r
- {\r
- if (fields.containsKey(Fields[lastfield]))\r
- {\r
- break;\r
- }\r
- }\r
-\r
- for (int i = 0; i < lastfield; i++)\r
- {\r
- value = (String) fields.get(Fields[i]);\r
- if (value != null && value.length() > 0)\r
- {\r
- desc += ( (String) fields.get(Fields[i])) + ":";\r
- }\r
- else\r
- {\r
- desc += Padding[i] + ":";\r
- }\r
- }\r
- }\r
- // just return the last field if no others were defined.\r
- if (fields.containsKey(Fields[lastfield]))\r
- {\r
- desc += (String) fields.get(Fields[lastfield]);\r
- }\r
- else\r
- {\r
- desc += ".";\r
- }\r
- return desc;\r
- }\r
-\r
- int getStartNum()\r
- {\r
- int start = 0;\r
- resCode val = getStartCode();\r
- if (val.val != null)\r
- {\r
- return val.val.intValue();\r
- }\r
- return start;\r
- }\r
-\r
- resCode getStartCode()\r
- {\r
- if (isModellerFieldset() && fields.containsKey(Fields[START] + "num"))\r
- {\r
- return (resCode) fields.get(Fields[START] + "num");\r
- }\r
- return null;\r
- }\r
-\r
- resCode getEndCode()\r
- {\r
- if (isModellerFieldset() && fields.containsKey(Fields[END] + "num"))\r
- {\r
- return (resCode) fields.get(Fields[END] + "num");\r
- }\r
- return null;\r
- }\r
-\r
- int getEndNum()\r
- {\r
- int end = 0;\r
- resCode val = getEndCode();\r
- if (val.val != null)\r
- {\r
- return val.val.intValue();\r
- }\r
- return end;\r
- }\r
-\r
- /**\r
- * returns true if sequence object was modifed with a valid modellerField set\r
- * @param newSeq SequenceI\r
- * @return boolean\r
- */\r
- boolean updateSequenceI(SequenceI newSeq)\r
- {\r
- if (isModellerFieldset())\r
- {\r
- if (getStartCode().val != null)\r
- {\r
- newSeq.setStart(getStartNum());\r
- }\r
- else\r
- {\r
- newSeq.setStart(1);\r
- }\r
- if (getEndCode().val != null)\r
- {\r
- newSeq.setEnd(getEndNum());\r
- }\r
- else\r
- {\r
- newSeq.setEnd(newSeq.getStart() + newSeq.getLength());\r
- }\r
- return true;\r
- }\r
- return false;\r
- }\r
-}\r
-\r
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.io;
+
+import jalview.bin.Cache;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.SequenceI;
+
+import java.util.List;
+
+import com.stevesoft.pat.Regex;
+
+public class ModellerDescription
+{
+ /**
+ * Translates between a String containing a set of colon-separated values on a
+ * single line, and sequence start/end and other properties. See PIRFile IO
+ * for its use.
+ */
+ final String[] seqTypes = { "sequence", "structure", "structureX",
+ "structureN" };
+
+ final String[] Fields = { "objectType", "objectId", "startField",
+ "startCode", "endField", "endCode", "description1", "description2",
+ "resolutionField", "tailField" };
+
+ final int TYPE = 0;
+
+ final int LOCALID = 1;
+
+ final int START = 2;
+
+ final int START_CHAIN = 3;
+
+ final int END = 4;
+
+ final int END_CHAIN = 5;
+
+ final int DESCRIPTION1 = 6;
+
+ final int DESCRIPTION2 = 7;
+
+ final int RESOLUTION = 8;
+
+ final int TAIL = 9;
+
+ /**
+ * 0 is free text or empty 1 is something that parses to an integer, or \@
+ */
+ final int Types[] = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 };
+
+ final char Padding[] = { ' ', ' ', ' ', '.', ' ', '.', '.', '.', '.',
+ '.' };
+
+ java.util.Hashtable fields = new java.util.Hashtable();
+
+ ModellerDescription()
+ {
+ fields.put(Fields[TAIL], "");
+ }
+
+ class resCode
+ {
+ Integer val;
+
+ String field;
+
+ resCode(String f, Integer v)
+ {
+ val = v;
+ field = f;
+ }
+
+ resCode(int v)
+ {
+ val = Integer.valueOf(v);
+ field = val.toString();
+ }
+ };
+
+ private resCode validResidueCode(String field)
+ {
+ Integer val = null;
+ Regex r = new Regex("\\s*((([-0-9]+).?)|FIRST|LAST|@)");
+
+ if (!r.search(field))
+ {
+ return null; // invalid
+ }
+ String value = r.stringMatched(3);
+ if (value == null)
+ {
+ value = r.stringMatched(1);
+ }
+ // Cache.debug("from '" + field + "' matched '" + value +
+ // "'");
+ try
+ {
+ val = Integer.valueOf(value);
+ return new resCode(field, val); // successful numeric extraction
+ } catch (Exception e)
+ {
+ }
+ return new resCode(field, null);
+ }
+
+ private java.util.Hashtable parseDescription(String desc)
+ {
+ java.util.Hashtable fields = new java.util.Hashtable();
+ java.util.StringTokenizer st = new java.util.StringTokenizer(desc, ":",
+ true);
+
+ String field;
+ int type = -1;
+ if (st.countTokens() > 0)
+ {
+ // parse colon-fields
+ int i = 0;
+ field = st.nextToken(":");
+ do
+ {
+ if (seqTypes[i].equalsIgnoreCase(field))
+ {
+ break;
+ }
+ } while (++i < seqTypes.length);
+
+ if (i < seqTypes.length)
+ {
+ st.nextToken(); // skip ':'
+ // valid seqType for modeller
+ type = i;
+ i = 1; // continue parsing fields
+ while (i < TAIL && st.hasMoreTokens())
+ {
+ if ((field = st.nextToken(":")) != null)
+ {
+ if (!field.equals(":"))
+ {
+ // validate residue field value
+ if (Types[i] == 1)
+ {
+ resCode val = validResidueCode(field);
+ if (val != null)
+ {
+ fields.put(new String(Fields[i] + "num"), val);
+ }
+ else
+ {
+ // Cache.debug(
+ // "Ignoring non-Modeller description: invalid integer-like
+ // field '" + field + "'");
+ type = -1; /* invalid field! - throw the FieldSet away */
+ }
+ ;
+ }
+ fields.put(Fields[i++], field);
+ if (st.hasMoreTokens())
+ {
+ st.nextToken(); // skip token sep.
+ }
+ }
+ else
+ {
+ i++;
+ }
+ }
+ }
+ if (i == TAIL)
+ {
+ // slurp remaining fields
+ while (st.hasMoreTokens())
+ {
+ String tl = st.nextToken(":");
+ field += tl.equals(":") ? tl : (":" + tl);
+ }
+ fields.put(Fields[TAIL], field);
+ }
+ }
+ }
+ if (type == -1)
+ {
+ // object is not a proper ModellerPIR object
+ fields = new java.util.Hashtable();
+ fields.put(Fields[TAIL], new String(desc));
+ }
+ else
+ {
+ fields.put(Fields[TYPE], seqTypes[type]);
+ }
+ return fields;
+ }
+
+ ModellerDescription(String desc)
+ {
+ if (desc == null)
+ {
+ desc = "";
+ }
+ fields = parseDescription(desc);
+ }
+
+ void setStartCode(int v)
+ {
+ resCode r;
+ fields.put(Fields[START] + "num", r = new resCode(v));
+ fields.put(Fields[START], r.field);
+ }
+
+ void setEndCode(int v)
+ {
+ resCode r;
+ fields.put(Fields[END] + "num", r = new resCode(v));
+ fields.put(Fields[END], r.field);
+ }
+
+ /**
+ * make a possibly updated modeller field line for the sequence object
+ *
+ * @param seq
+ * SequenceI
+ */
+ ModellerDescription(SequenceI seq)
+ {
+
+ if (seq.getDescription() != null)
+ {
+ fields = parseDescription(seq.getDescription());
+ }
+
+ if (isModellerFieldset())
+ {
+ // Set start and end before we update the type (in the case of a
+ // synthesized field set)
+ if (getStartCode() == null || (getStartNum() != seq.getStart()
+ && getStartCode().val != null))
+ {
+ // unset or user updated sequence start position
+ setStartCode(seq.getStart());
+ }
+
+ if (getEndCode() == null || (getEndNum() != seq.getEnd()
+ && getStartCode() != null && getStartCode().val != null))
+ {
+ setEndCode(seq.getEnd());
+ }
+ }
+ else
+ {
+ // synthesize fields
+ setStartCode(seq.getStart());
+ setEndCode(seq.getEnd());
+ fields.put(Fields[LOCALID], seq.getName()); // this may be overwritten
+ // below...
+ // type - decide based on evidence of PDB database references - this also
+ // sets the local reference field
+ int t = 0; // sequence
+ if (seq.getDatasetSequence() != null
+ && seq.getDatasetSequence().getDBRefs() != null)
+ {
+ List<DBRefEntry> dbr = seq.getDatasetSequence().getDBRefs();
+ for (int i = 0, ni = dbr.size(); i < ni; i++)
+ {
+ DBRefEntry dbri = dbr.get(i);
+ if (dbri != null)
+ {
+ // JBPNote PDB dbRefEntry needs properties to propagate onto
+ // ModellerField
+ // JBPNote Need to get info from the user about whether the sequence
+ // is the one being modelled, or if it is a template.
+ if (dbri.getSource().equals(jalview.datamodel.DBRefSource.PDB))
+ {
+ fields.put(Fields[LOCALID], dbri.getAccessionId());
+ t = 2;
+ break;
+ }
+ }
+ }
+ }
+ fields.put(Fields[TYPE], seqTypes[t]);
+ }
+
+ }
+
+ /**
+ * Indicate if fields parsed to a modeller-like colon-separated value line
+ *
+ * @return boolean
+ */
+ boolean isModellerFieldset()
+ {
+ return (fields.containsKey(Fields[TYPE]));
+ }
+
+ String getDescriptionLine()
+ {
+ String desc = "";
+ int lastfield = Fields.length - 1;
+
+ if (isModellerFieldset())
+ {
+ String value;
+ // try to write a minimal modeller field set, so..
+
+ // find the last valid field in the entry
+
+ for (; lastfield > 6; lastfield--)
+ {
+ if (fields.containsKey(Fields[lastfield]))
+ {
+ break;
+ }
+ }
+
+ for (int i = 0; i < lastfield; i++)
+ {
+ value = (String) fields.get(Fields[i]);
+ if (value != null && value.length() > 0)
+ {
+ desc += ((String) fields.get(Fields[i])) + ":";
+ }
+ else
+ {
+ desc += Padding[i] + ":";
+ }
+ }
+ }
+ // just return the last field if no others were defined.
+ if (fields.containsKey(Fields[lastfield]))
+ {
+ desc += (String) fields.get(Fields[lastfield]);
+ }
+ else
+ {
+ desc += ".";
+ }
+ return desc;
+ }
+
+ int getStartNum()
+ {
+ int start = 0;
+ resCode val = getStartCode();
+ if (val != null && val.val != null)
+ {
+ return val.val.intValue();
+ }
+ return start;
+ }
+
+ resCode getStartCode()
+ {
+ if (isModellerFieldset() && fields.containsKey(Fields[START] + "num"))
+ {
+ return (resCode) fields.get(Fields[START] + "num");
+ }
+ return null;
+ }
+
+ resCode getEndCode()
+ {
+ if (isModellerFieldset() && fields.containsKey(Fields[END] + "num"))
+ {
+ return (resCode) fields.get(Fields[END] + "num");
+ }
+ return null;
+ }
+
+ int getEndNum()
+ {
+ int end = 0;
+ resCode val = getEndCode();
+ if (val != null && val.val != null)
+ {
+ return val.val.intValue();
+ }
+ return end;
+ }
+
+ /**
+ * returns true if sequence object was modifed with a valid modellerField set
+ *
+ * @param newSeq
+ * SequenceI
+ * @return boolean
+ */
+ boolean updateSequenceI(SequenceI newSeq)
+ {
+ if (isModellerFieldset())
+ {
+ resCode rc = getStartCode();
+ if (rc != null && rc.val != null)
+ {
+ newSeq.setStart(getStartNum());
+ }
+ else
+ {
+ newSeq.setStart(1);
+ }
+ rc = getEndCode();
+ if (rc != null && rc.val != null)
+ {
+ newSeq.setEnd(getEndNum());
+ }
+ else
+ {
+ newSeq.setEnd(newSeq.getStart() + newSeq.getLength());
+ }
+ return true;
+ }
+ return false;
+ }
+}