JAL-3445 preliminary BSML reader
[jalview.git] / src / jalview / io / BSMLFile.java
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.Sequence;
24 import jalview.datamodel.SequenceFeature;
25 import jalview.datamodel.SequenceI;
26 import jalview.util.MessageManager;
27
28 import java.io.BufferedReader;
29 import java.io.FileNotFoundException;
30 import java.io.FileReader;
31 import java.io.IOException;
32 import java.util.Hashtable;
33 import java.util.Map;
34
35 import javax.xml.parsers.DocumentBuilder;
36 import javax.xml.parsers.DocumentBuilderFactory;
37 import javax.xml.parsers.ParserConfigurationException;
38
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41 import org.w3c.dom.NodeList;
42 import org.xml.sax.InputSource;
43 import org.xml.sax.SAXException;
44
45 import fr.orsay.lri.varna.exceptions.ExceptionFileFormatOrSyntax;
46 import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed;
47 import fr.orsay.lri.varna.exceptions.ExceptionPermissionDenied;
48
49 /**
50  * Preliminary reader for Bioinformatics Sequence Markup Language
51  * http://www.bsml.org
52  * 
53  * @author hansonr
54  *
55  */
56 public class BSMLFile extends AlignFile
57 {
58
59   public BSMLFile()
60   {
61     super();
62
63   }
64
65   public BSMLFile(String inFile, DataSourceType type) throws IOException
66   {
67     super(inFile, type);
68
69   }
70
71   public BSMLFile(FileParse source) throws IOException
72   {
73     super(source);
74
75   }
76
77   public BufferedReader CreateReader() throws FileNotFoundException
78   {
79     FileReader fr = null;
80     fr = new FileReader(inFile);
81
82     BufferedReader r = new BufferedReader(fr);
83     return r;
84   }
85
86   /*
87    * (non-Javadoc)
88    * 
89    * @see jalview.io.AlignFile#parse()
90    */
91   @Override
92   public void parse() throws IOException
93   {
94     try
95     {
96       _parse();
97     } catch (ExceptionPermissionDenied pdx)
98     {
99       errormessage = MessageManager.formatMessage(
100               "exception.BSML_couldnt_access_datasource", new String[]
101               { pdx.getMessage() });
102       throw new IOException(pdx);
103     } catch (ExceptionLoadingFailed lf)
104     {
105       errormessage = MessageManager.formatMessage(
106               "exception.BSML_couldnt_process_data", new String[]
107               { lf.getMessage() });
108       throw new IOException(lf);
109     } catch (ExceptionFileFormatOrSyntax iff)
110     {
111       errormessage = MessageManager
112               .formatMessage("exception.BSML_invalid_file", new String[]
113               { iff.getMessage() });
114       throw new IOException(iff);
115     } catch (Exception x)
116     {
117       error = true;
118       errormessage = MessageManager.formatMessage(
119               "exception.BSML_problem_parsing_data", new String[]
120               { x.getMessage() });
121       throw new IOException(errormessage, x);
122     }
123   }
124
125   @SuppressWarnings("unchecked")
126   public void _parse()
127           throws ExceptionPermissionDenied, ExceptionLoadingFailed,
128           ExceptionFileFormatOrSyntax, ParserConfigurationException,
129           SAXException, IOException
130   {
131
132     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
133
134     dbf.setIgnoringElementContentWhitespace(true);
135     dbf.setIgnoringComments(true);
136     dbf.setValidating(true);
137     dbf.setCoalescing(true);
138     dbf.setNamespaceAware(true);
139       dbf.setFeature("http://xml.org/sax/features/namespaces", false);
140       dbf.setFeature("http://xml.org/sax/features/validation", false);
141       dbf.setFeature(
142               "http://apache.org/xml/features/nonvalidating/load-dtd-grammar",
143               false);
144       dbf.setFeature(
145               "http://apache.org/xml/features/nonvalidating/load-external-dtd",
146               false);
147
148       DocumentBuilder db = dbf.newDocumentBuilder();
149
150       Map<String, SequenceI> htSeq = new Hashtable<>();
151       InputSource is = new InputSource(getReader());
152       Document d = db.parse(is);
153       NodeList sequences = d.getElementsByTagName("Sequence-data");
154       int n = sequences.getLength();
155       SequenceI[] sqs = new SequenceI[n];
156       for (int i = 0; i < n; i++)
157       {
158         Element e = (Element) sequences.item(i);
159         String s = e.getTextContent();
160         String id = e.getAttribute("seq-name");
161         SequenceI seq = sqs[i] = new Sequence(id, s, 1, s.length());
162         htSeq.put(id, seq);
163         // ?? sqs[i].setEnd(sqs[i].findPosition(sqs[i].getLength()));
164       }
165
166       sequences = d.getElementsByTagName("Sequence");
167       n = sequences.getLength();
168       for (int i = 0; i < n; i++)
169       {
170         Element e = (Element) sequences.item(i);
171         String mol = e.getAttribute("molecule"); // dna or rna
172         if (!"dna".equals(mol))
173         {
174           System.err.println("BSML molecule=rna not implemented");
175           continue;
176         }
177         String title = e.getAttribute("title");
178         SequenceI seq = htSeq.get(title);
179         if (seq == null)
180         {
181           continue;
182         }
183       NodeList features = e.getElementsByTagName("Feature");
184         int featureCount = features.getLength();
185         for (int f = 0; f < featureCount; f++)
186         {
187           Element feature = (Element) features.item(f);
188           // <Feature class="GENE" title="CPXV-GER_1980_EP4-211">
189           // <Interval-loc complement="0" endpos="217104" startpos="216643"/>
190           // <Resource id="GENE-ID:119705"/>
191           // </Feature>
192         Element iloc = (Element) feature
193                 .getElementsByTagName("Interval-loc").item(0);
194           String complement = iloc.getAttribute("complement");
195           if (!"0".equals(complement))
196           {
197             // Jalview cannot handle complement genes (running backward on the
198             // complementary strand);
199             continue;
200           }
201           String fclass = feature.getAttribute("class");
202           if (!"GENE".equals(fclass))
203           {
204             // just processing GENE features for now;
205             continue;
206           }
207           String ftitle = feature.getAttribute("title");
208         int start = Integer.parseInt(iloc.getAttribute("startpos"));
209         int end = Integer.parseInt(iloc.getAttribute("endpos"));
210         SequenceFeature sf = new SequenceFeature("GENE", ftitle, start, end,
211                 null);
212         seq.addSequenceFeature(sf);
213         }
214         setSeqs(sqs);
215       }
216
217   }
218
219   @Override
220   public String print(SequenceI[] s, boolean jvSuffix)
221   {
222     return "not yet implemented";
223   }
224
225 }