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 */
021package org.biojava.nbio.protmod.io;
022
023import org.biojava.nbio.protmod.ProteinModification;
024import org.biojava.nbio.protmod.ProteinModificationRegistry;
025import org.biojava.nbio.protmod.structure.*;
026import org.biojava.nbio.core.util.PrettyXMLWriter;
027import org.slf4j.Logger;
028import org.slf4j.LoggerFactory;
029import org.w3c.dom.Document;
030import org.w3c.dom.NamedNodeMap;
031import org.w3c.dom.Node;
032import org.w3c.dom.NodeList;
033import org.xml.sax.InputSource;
034import org.xml.sax.SAXException;
035import org.xml.sax.SAXParseException;
036
037import javax.xml.parsers.DocumentBuilder;
038import javax.xml.parsers.DocumentBuilderFactory;
039import java.io.IOException;
040import java.io.PrintWriter;
041import java.io.StringReader;
042import java.io.StringWriter;
043import java.util.*;
044
045public class ModifiedCompoundXMLConverter {
046
047        private static final Logger logger = LoggerFactory.getLogger(ModifiedCompoundXMLConverter.class);
048
049        public static String toXML(ModifiedCompound mc) throws IOException{
050
051                if ( mc == null) {
052                        logger.warn("ModifiedCompound == null! ");
053                        return "<modifiedCompound/>";
054                }
055                StringWriter out = new StringWriter();
056
057                PrettyXMLWriter xml = new PrettyXMLWriter(new PrintWriter(out));
058
059                ProteinModification protMod = mc.getModification();
060                String modificationId = protMod==null?null:protMod.getId();
061
062                xml.openTag("modifiedCompound");
063                if ( modificationId != null) {
064//                      ProteinModificationXMLConverter.toXML(modification, xml);
065                        xml.openTag("proteinModification");
066                        xml.attribute("id", modificationId);
067                        xml.closeTag("proteinModification");
068                }
069
070
071                Set<StructureAtomLinkage > linkages = mc.getAtomLinkages();
072                if ( linkages.size() > 0 ) {
073                        int pos = -1;
074                        for ( StructureAtomLinkage link: linkages){
075                                pos ++;
076                                xml.openTag("linkage");
077                                xml.attribute("pos", pos+"");
078                                xml.attribute("total", linkages.size()+"");
079                                StructureAtom atom1 = link.getAtom1();
080                                StructureAtom atom2 = link.getAtom2();
081                                double distance = link.getDistance();
082
083                                xml.attribute("distance", distance+"");
084                                xml.openTag("atom1");
085                                StructureAtomXMLConverter.toXML(atom1,xml);
086                                xml.closeTag("atom1");
087                                xml.openTag("atom2");
088                                StructureAtomXMLConverter.toXML(atom2,xml);
089                                xml.closeTag("atom2");
090                                xml.closeTag("linkage");
091                        }
092                } else {
093                        // no linkages, need to serialize the residues...
094                        xml.openTag("linkage");
095                        xml.closeTag("linkage");
096                        Set<StructureGroup> groups = mc.getGroups();
097                        for (StructureGroup group : groups) {
098                                StructureGroupXMLConverter.toXML(group, xml);
099                        }
100                }
101
102
103
104
105                xml.closeTag("modifiedCompound");
106                return out.toString();
107        }
108
109        public static ModifiedCompound fromXML(String xml){
110                ProteinModification modification = null;
111                //Collection<StructureAtomLinkage> linkages = new ArrayList<StructureAtomLinkage>();
112                StructureAtomLinkage[] linkages = null;
113                List<StructureGroup> structureGroups = new ArrayList<StructureGroup>();
114                try
115                {
116                        //Convert string to XML document
117                        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
118                        DocumentBuilder db = factory.newDocumentBuilder();
119                        InputSource inStream = new InputSource();
120                        inStream.setCharacterStream(new StringReader(xml));
121                        Document doc = db.parse(inStream);
122
123                        // normalize text representation
124                        doc.getDocumentElement().normalize();
125
126                        NodeList listOfmodifications = doc.getElementsByTagName("modifiedCompound");
127                        //int numArrays = listOfArrays.getLength();
128                        // go over the blocks
129                        for(int modPos=0; modPos<listOfmodifications.getLength() ; modPos++)
130                        {
131
132                                Node modificationElement       = listOfmodifications.item(modPos);
133
134                                NodeList children = modificationElement.getChildNodes();
135
136                                int numChildren  = children.getLength();
137
138
139                                for ( int e =0; e< numChildren ; e++){
140                                        Node  listOfConditions = children.item(e);
141
142                                        if(!listOfConditions.hasAttributes()) continue;
143
144
145                                        if ( listOfConditions.getNodeName().equals("proteinModification")) {
146                                                //modification = ProteinModificationXMLConverter.fromXML(listOfConditions);
147                                                String modId = getAttribute(listOfConditions, "id");
148                                                modification = ProteinModificationRegistry.getById(modId);
149                                                if (modification==null) {
150                                                        logger.warn("Error: no modification information.");
151                                                }
152                                        } else if ( listOfConditions.getNodeName().equals("linkage")) {
153                                                double dist = Double.parseDouble(getAttribute(listOfConditions, "distance"));
154                                                int pos = Integer.parseInt(getAttribute(listOfConditions,"pos"));
155                                                int total = Integer.parseInt(getAttribute(listOfConditions,"total"));
156                                                if ( linkages == null)
157                                                        linkages = new StructureAtomLinkage[total];
158
159                                                StructureAtom atom1 = getAtom("atom1", listOfConditions);
160                                                StructureAtom atom2 = getAtom("atom2",listOfConditions);
161                                                StructureAtomLinkage linkage = new StructureAtomLinkage(atom1, atom2, dist);
162                                                //linkages.add(linkage);
163                                                linkages[pos] = linkage;
164                                        } else if (listOfConditions.getNodeName().equals("structureGroup")) {
165                                                StructureGroup group = StructureGroupXMLConverter.fromXML(listOfConditions);
166                                                structureGroups.add(group);
167//                                              logger.info("structureGroups size:" + structureGroups.size());
168                                        }
169                                }
170                        }
171                } catch (SAXParseException err) {
172                        logger.error("** Parsing error, line: {}, uri: {}", err.getLineNumber (), err.getSystemId (), err);
173                }
174                catch (SAXException e) {
175                        logger.error("Exception: ", e);
176                }
177                catch (Throwable t) {
178                        logger.error("Exception: ", t);
179                }
180
181
182                if ( linkages != null) {
183                        Collection<StructureAtomLinkage> links = Arrays.asList(linkages);
184                        return new ModifiedCompoundImpl(modification, links);
185                } else if ( structureGroups.size() == 1) {
186                        return new ModifiedCompoundImpl(modification, structureGroups.get(0));
187                }
188                return null;
189
190        }
191
192
193
194        private static StructureAtom getAtom(String elementName, Node n) {
195
196                NodeList children = n.getChildNodes();
197
198                int numChildren  = children.getLength();
199
200                StructureAtom atom = null;
201                for ( int e =0; e< numChildren ; e++){
202                        Node  atoms = children.item(e);
203
204                        if ( atoms.getNodeName().equals(elementName)) {
205                                NodeList child2 = atoms.getChildNodes();
206                                int numAtoms = child2.getLength();
207                                //logger.info("got " + numAtoms + " atoms");
208                                for ( int a=0;a< numAtoms; a++){
209                                        Node atomNode = child2.item(a);
210                                        if(!atomNode.hasAttributes()) continue;
211                                        atom = StructureAtomXMLConverter.fromXML(atomNode);
212                                        return atom;
213                                }
214
215                        }
216                }
217                return atom;
218        }
219
220        private static String getAttribute(Node node, String attr){
221                if( ! node.hasAttributes())
222                        return null;
223
224                NamedNodeMap atts = node.getAttributes();
225
226                if ( atts == null)
227                        return null;
228
229                Node att = atts.getNamedItem(attr);
230                if ( att == null)
231                        return null;
232
233                String value = att.getTextContent();
234
235                return value;
236
237        }
238
239}