1 /* Copyright (C) 2011  Egon Willighagen <egonw@users.sf.net>
2  *
3  * Contact: cdk-devel@slists.sourceforge.net
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License
7  * as published by the Free Software Foundation; either version 2.1
8  * of the License, or (at your option) any later version.
9  * All we ask is that proper credit is given for our work, which includes
10  * - but is not limited to - adding the above copyright notice to the beginning
11  * of your source code files, and to any copyright notice that you may distribute
12  * with programs based on this work.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 package org.openscience.cdk.io;
24 
25 import java.io.ByteArrayInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.InputStreamReader;
29 import java.util.List;
30 
31 import org.junit.Assert;
32 import org.junit.BeforeClass;
33 import org.junit.Test;
34 import org.openscience.cdk.ChemFile;
35 import org.openscience.cdk.DefaultChemObjectBuilder;
36 import org.openscience.cdk.exception.CDKException;
37 import org.openscience.cdk.interfaces.IAtom;
38 import org.openscience.cdk.interfaces.IAtomContainer;
39 import org.openscience.cdk.interfaces.IBond;
40 import org.openscience.cdk.interfaces.IChemFile;
41 import org.openscience.cdk.tools.manipulator.ChemFileManipulator;
42 import org.openscience.cdk.tools.periodictable.PeriodicTable;
43 
44 /**
45  * TestCase for reading CML files.
46  *
47  * @cdk.module test-io
48  */
49 public class CMLReaderTest extends SimpleChemObjectReaderTest {
50 
51     @BeforeClass
setup()52     public static void setup() {
53         setSimpleChemObjectReader(new CMLReader(), "data/cml/3.cml");
54     }
55 
56     @Test
testAccepts()57     public void testAccepts() {
58         Assert.assertTrue(chemObjectIO.accepts(ChemFile.class));
59     }
60 
61     @Test(expected = CDKException.class)
62     @Override
testSetReader_Reader()63     public void testSetReader_Reader() throws Exception {
64         InputStream ins = ChemObjectReaderTest.class.getClassLoader().getResourceAsStream(testFile);
65         chemObjectIO.setReader(new InputStreamReader(ins));
66     }
67 
68     /**
69      * Ensure stereoBond content is read if the usual "dictRef" attribute is not
70      * supplied
71      *
72      * @cdk.bug 1248
73      */
74     @Test
testBug1248()75     public void testBug1248() throws IOException, CDKException {
76 
77         InputStream in = getClass().getResourceAsStream("/data/cml/(1R)-1-aminoethan-1-ol.cml");
78         CMLReader reader = new CMLReader(in);
79         try {
80             IChemFile cfile = reader.read(DefaultChemObjectBuilder.getInstance().newInstance(IChemFile.class));
81 
82             Assert.assertNotNull("ChemFile was Null", cfile);
83 
84             List<IAtomContainer> containers = ChemFileManipulator.getAllAtomContainers(cfile);
85 
86             Assert.assertEquals("Expected a single atom container", 1, containers.size());
87 
88             IAtomContainer container = containers.get(0);
89 
90             Assert.assertNotNull("Null atom container read", container);
91 
92             IBond bond = container.getBond(2);
93 
94             Assert.assertNotNull("Null bond", bond);
95 
96             Assert.assertEquals("Expected Wedge (Up) Bond", IBond.Stereo.UP, bond.getStereo());
97 
98         } finally {
99             reader.close();
100         }
101 
102     }
103 
104     /**
105      * Ensure correct atomic numbers are read and does not default to 1
106      *
107      * @cdk.bug 1245
108      */
109     @Test
testBug1245()110     public void testBug1245() throws IOException, CDKException {
111 
112         InputStream in = getClass().getResourceAsStream("/data/cml/(1R)-1-aminoethan-1-ol.cml");
113         CMLReader reader = new CMLReader(in);
114         try {
115             IChemFile cfile = reader.read(DefaultChemObjectBuilder.getInstance().newInstance(IChemFile.class));
116 
117             Assert.assertNotNull("ChemFile was Null", cfile);
118 
119             List<IAtomContainer> containers = ChemFileManipulator.getAllAtomContainers(cfile);
120 
121             Assert.assertEquals("Expected a single atom container", 1, containers.size());
122 
123             IAtomContainer container = containers.get(0);
124 
125             Assert.assertNotNull("Null atom container read", container);
126 
127             for (IAtom atom : container.atoms()) {
128                 Assert.assertEquals("Incorrect atomic number", PeriodicTable.getAtomicNumber(atom.getSymbol()),
129                         atom.getAtomicNumber());
130             }
131 
132         } finally {
133             reader.close();
134         }
135     }
136 
137     /**
138      * Ensures that when multiple stereo is set the dictRef is favoured
139      * and the charContent is not used. Here is an example of what we expect
140      * to read.
141      *
142      * <pre>{@code
143      * <bond atomRefs2="a1 a4" order="1">
144      *     <bondStereo dictRef="cml:W"/> <!-- should be W -->
145      * </bond>
146      *
147      * <bond atomRefs2="a1 a4" order="1">
148      *     <bondStereo>W</bondStereo> <!-- should be W -->
149      * </bond>
150      *
151      * <bond atomRefs2="a1 a4" order="1">
152      *    <bondStereo dictRef="cml:W">W</bondStereo> <!-- should be W -->
153      * </bond>
154      *
155      * <bond atomRefs2="a1 a4" order="1">
156      *    <bondStereo dictRef="cml:W">H</bondStereo> <!-- should be W -->
157      * </bond>
158      * }</pre>
159      *
160      * @cdk.bug 1274
161      * @see #testBug1248()
162      */
163     @Test
testBug1274()164     public void testBug1274() throws CDKException, IOException {
165 
166         InputStream in = getClass().getResourceAsStream("/data/cml/(1R)-1-aminoethan-1-ol-multipleBondStereo.cml");
167         CMLReader reader = new CMLReader(in);
168         try {
169             IChemFile cfile = reader.read(DefaultChemObjectBuilder.getInstance().newInstance(IChemFile.class));
170 
171             Assert.assertNotNull("ChemFile was null", cfile);
172 
173             List<IAtomContainer> containers = ChemFileManipulator.getAllAtomContainers(cfile);
174 
175             Assert.assertEquals("expected a single atom container", 1, containers.size());
176 
177             IAtomContainer container = containers.get(0);
178 
179             Assert.assertNotNull("null atom container read", container);
180 
181             // we check here that the charContent is not used and also that more then
182             // one stereo isn't set
183             Assert.assertEquals("expected non-stereo bond", IBond.Stereo.NONE, container.getBond(0).getStereo());
184             Assert.assertEquals("expected Hatch (Down) Bond", IBond.Stereo.DOWN, container.getBond(1).getStereo());
185             Assert.assertEquals("expected non-stereo bond", IBond.Stereo.NONE, container.getBond(2).getStereo());
186 
187         } finally {
188             reader.close();
189         }
190     }
191 
192     /**
193      * Ensures that {@code <bondStereo dictRef="cml:"/>} doesn't cause an exception
194      *
195      * @cdk.bug 1275
196      */
197     @Test
testBug1275()198     public void testBug1275() throws CDKException, IOException {
199 
200         InputStream in = getClass().getResourceAsStream("/data/cml/(1R)-1-aminoethan-1-ol-malformedDictRef.cml");
201         CMLReader reader = new CMLReader(in);
202         try {
203             IChemFile cfile = reader.read(DefaultChemObjectBuilder.getInstance().newInstance(IChemFile.class));
204 
205             Assert.assertNotNull("ChemFile was null", cfile);
206 
207             List<IAtomContainer> containers = ChemFileManipulator.getAllAtomContainers(cfile);
208 
209             Assert.assertEquals("expected a single atom container", 1, containers.size());
210 
211             IAtomContainer container = containers.get(0);
212 
213             Assert.assertNotNull("null atom container read", container);
214 
215             // we check here that the malformed dictRef doesn't throw an exception
216             Assert.assertEquals("expected non-stereo bond", IBond.Stereo.NONE, container.getBond(0).getStereo());
217             Assert.assertEquals("expected Wedge (Up) Bond", IBond.Stereo.UP, container.getBond(1).getStereo());
218             Assert.assertEquals("expected non-stereo bond", IBond.Stereo.NONE, container.getBond(2).getStereo());
219 
220         } finally {
221             reader.close();
222         }
223 
224     }
225 
226     @Test
testWedgeBondParsing()227     public void testWedgeBondParsing() throws CDKException, IOException {
228         InputStream in = getClass().getResourceAsStream("/data/cml/AZD5423.xml");
229         CMLReader reader = new CMLReader(in);
230         try {
231             IChemFile cfile = reader.read(DefaultChemObjectBuilder.getInstance().newInstance(IChemFile.class));
232             Assert.assertNotNull("ChemFile was null", cfile);
233             List<IAtomContainer> containers = ChemFileManipulator.getAllAtomContainers(cfile);
234             Assert.assertEquals("expected a single atom container", 1, containers.size());
235             IAtomContainer container = containers.get(0);
236             Assert.assertNotNull("null atom container read", container);
237 
238             // we check here that the malformed dictRef doesn't throw an exception
239             for (int i = 0; i < 19; i++) {
240                 Assert.assertEquals(
241                         "found an unexpected wedge bond for " + i + ": " + container.getBond(i).getStereo(),
242                         IBond.Stereo.NONE, container.getBond(i).getStereo());
243             }
244             Assert.assertEquals("expected a wedge bond", IBond.Stereo.DOWN, container.getBond(19).getStereo());
245             for (int i = 20; i < 30; i++) {
246                 Assert.assertEquals(
247                         "found an unexpected wedge bond for " + i + ": " + container.getBond(i).getStereo(),
248                         IBond.Stereo.NONE, container.getBond(i).getStereo());
249             }
250             Assert.assertEquals("expected a wedge bond", IBond.Stereo.UP, container.getBond(30).getStereo());
251             for (int i = 31; i <= 37; i++) {
252                 Assert.assertEquals(
253                         "found an unexpected wedge bond for " + i + ": " + container.getBond(i).getStereo(),
254                         IBond.Stereo.NONE, container.getBond(i).getStereo());
255             }
256         } finally {
257             reader.close();
258         }
259     }
260 
261     @Test
testSFBug1085912_1()262     public void testSFBug1085912_1() throws Exception {
263         String cmlContent = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
264                 + "<molecule convention=\"PDB\" dictRef=\"pdb:model\" xmlns=\"http://www.xml-cml.org/schema\">"
265                 + "  <molecule dictRef=\"pdb:sequence\" id=\"ALAA116\">"
266                 + "    <atomArray>"
267                 + "      <atom id=\"a9794931\" elementType=\"N\" x3=\"-10.311\" y3=\"2.77\" z3=\"-9.837\" formalCharge=\"0\">"
268                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
269                 + "      </atom>"
270                 + "      <atom id=\"a5369354\" elementType=\"C\" x3=\"-9.75\" y3=\"4.026\" z3=\"-9.35\" formalCharge=\"0\">"
271                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
272                 + "      </atom>"
273                 + "      <atom id=\"a14877152\" elementType=\"C\" x3=\"-10.818\" y3=\"5.095\" z3=\"-9.151\" formalCharge=\"0\">"
274                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
275                 + "      </atom>"
276                 + "      <atom id=\"a26221736\" elementType=\"O\" x3=\"-11.558\" y3=\"5.433\" z3=\"-10.074\" formalCharge=\"0\">"
277                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
278                 + "      </atom>"
279                 + "      <atom id=\"a4811470\" elementType=\"C\" x3=\"-8.678\" y3=\"4.536\" z3=\"-10.304\" formalCharge=\"0\">"
280                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
281                 + "      </atom>"
282                 + "      <atom id=\"a211489\" elementType=\"H\" x3=\"-10.574\" y3=\"2.695\" z3=\"-10.778\" formalCharge=\"0\">"
283                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
284                 + "      </atom>"
285                 + "      <atom id=\"a31287617\" elementType=\"H\" x3=\"-9.279\" y3=\"3.829\" z3=\"-8.398\" formalCharge=\"0\">"
286                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
287                 + "      </atom>"
288                 + "      <atom id=\"a19487109\" elementType=\"H\" x3=\"-8.523\" y3=\"3.813\" z3=\"-11.09\" formalCharge=\"0\">"
289                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
290                 + "      </atom>"
291                 + "      <atom id=\"a28589522\" elementType=\"H\" x3=\"-8.994\" y3=\"5.477\" z3=\"-10.737\" formalCharge=\"0\">"
292                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
293                 + "      </atom>"
294                 + "      <atom id=\"a4638116\" elementType=\"H\" x3=\"-7.754\" y3=\"4.682\" z3=\"-9.763\" formalCharge=\"0\">"
295                 + "        <scalar dictRef=\"cdk:partialCharge\" dataType=\"xsd:double\">0.0</scalar>"
296                 + "      </atom>" + "    </atomArray>" + "  </molecule>" + "</molecule>";
297         CMLReader reader = new CMLReader(new ByteArrayInputStream(cmlContent.getBytes()));
298         try {
299             IChemFile cfile = reader.read(DefaultChemObjectBuilder.getInstance().newInstance(IChemFile.class));
300             Assert.assertNotNull("ChemFile was null", cfile);
301             List<IAtomContainer> containers = ChemFileManipulator.getAllAtomContainers(cfile);
302             Assert.assertEquals("expected a single atom container", 1, containers.size());
303             IAtomContainer container = containers.get(0);
304             Assert.assertNotNull("null atom container read", container);
305 
306             // OK, now test that the residue identifier is properly read
307             Assert.assertEquals("ALAA116", container.getID());
308         } finally {
309             reader.close();
310         }
311     }
312 
313     @Test
testMixedNamespaces()314     public void testMixedNamespaces() throws Exception {
315         InputStream in = getClass().getResourceAsStream("US06358966-20020319-C00001-enr.cml");
316         CMLReader reader = new CMLReader(in);
317         try {
318             IChemFile cfile = reader.read(DefaultChemObjectBuilder.getInstance().newInstance(IChemFile.class));
319             Assert.assertEquals(34, ChemFileManipulator.getAtomCount(cfile));
320             Assert.assertEquals(39, ChemFileManipulator.getBondCount(cfile));
321         } finally {
322             reader.close();
323         }
324 
325     }
326 }
327