1 /**********************************************************************
2 Copyright (C) 2004 by Chris Morley
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13
14 /* This is a heavily commented template for a OpenBabel format class.
15
16 Format classes are plugins: no modifications are needed to existing code
17 to indroduce a new format. The code just needs to be compiled and linked
18 with the rest of the OpenBabel code.
19 Alternatively, they can be built (either singly or in groups) as DLLs
20 or shared libraries. [**Extra build info**]
21
22 Each file may contain more than one format.
23
24 This compilable, but non-functional example is for a format which
25 converts a molecule to and from OpenBabel's internal format OBMol.
26 The conversion framework can handle other types of object, provided
27 they are derived from OBBase, such as OBReaction, OBText.
28
29 For XML formats, extra support for the parsing is provided, see pubchem.cpp
30 as an example.
31 */
32
33 #include <openbabel/babelconfig.h>
34 #include <openbabel/obmolecformat.h>
35
36 using namespace std;
37 namespace OpenBabel
38 {
39
40 class XXXFormat : public OBMoleculeFormat
41 // Derive directly from OBFormat for objects which are not molecules.
42 {
43 public:
44 //Register this format type ID in the constructor
XXXFormat()45 XXXFormat()
46 {
47 /* XXX is the file extension and is case insensitive. A MIME type can be
48 added as an optional third parameter.
49 Multiple file extensions can be registered by adding extra statements.*/
50 OBConversion::RegisterFormat("XXX",this);
51
52 /* If there are any format specific options they should be registered here
53 so that the commandline interface works properly.
54 The first parameter is the option name. If it is a single letter it can be
55 concatinated with other single letter options. For output options it can be
56 multicharcter and is then written as --optionname on the command line.
57 The third parameter is the number of parameters the option takes. Currently
58 this is either 1 or 0 and if it is 0 can be omitted for output options.
59 The parameter is always text and needs to be parsed to extract a number.
60
61 Options can apply when writing - 4th parameter is OBConversion::OUTOPTIONS
62 or can be omitted as shown. A single letter output option is preceded
63 by -x on the command line.
64 Or options can apply to the input format - the 4th parameter is
65 OBConversion::INOPTIONS. They are then preceded by -a on the command line.
66
67 Each option letter may be reused in other formats, but within the same group,
68 INOPTIONS or OUTOPTIONS, must take the same number of parameters (0 or 1).
69 There will be an error message when OpenBabel runs if there are conflicts
70 between formats. A list of formats currently used (which may not be
71 comprehensive) is in docs/options.html.
72 */
73 OBConversion::RegisterOptionParam("f", this, 1);
74 OBConversion::RegisterOptionParam("n", this);
75 OBConversion::RegisterOptionParam("s", this, 0, OBConversion::INOPTIONS);
76
77 }
78
79 /* The first line of the description should be a brief identifier, <40 chars, because
80 it is used in dropdown lists, etc. in some user interfaces. The rest is optional.
81
82 Describe any format specific options here. This text is parsed to provide
83 checkboxes, etc for the GUI (for details click the control menu),
84 so please try to keep to a similar form.
85
86 Write options are the most common, and the "Write" is optional.
87 The option f takes a text parameter, so that it is essential that the option
88 is registered in the constructor of the class.
89 Finish the options with a blank line as shown, if there are more than one
90 group of options, or if there are further comments after them.
91 */
Description()92 virtual const char* Description() //required
93 {
94 return
95 "XXX format\n"
96 "Some comments here, on as many lines as necessay\n"
97 "Write Options e.g. -xf3 \n"
98 " f# Number of (fictional) levels\n"
99 " n Omit (virtual) title\n\n"
100
101 "Read Options e.g. -as\n"
102 " s Consider single bonds only\n"
103 ;
104 };
105
106 //Optional URL where the file format is specified
SpecificationURL()107 virtual const char* SpecificationURL(){ return ""; }
108
109 //Optional
GetMIMEType()110 virtual const char* GetMIMEType()
111 { return "chemical/x-xxx"; };
112
113
114 /* Flags() can return be any of the following combined by |
115 or be omitted if none apply
116 NOTREADABLE READONEONLY NOTWRITABLE WRITEONEONLY DEFAULTFORMAT
117 READBINARY WRITEBINARY READXML ZEROATOMSOK*/
Flags()118 virtual unsigned int Flags()
119 {
120 return READONEONLY;
121 };
122
123 /* This optional function is for formats which can contain more than one
124 molecule. It is used to quickly position the input stream after the nth
125 molecule without have to convert and discard all the n molecules.
126 See obconversion.cpp for details and mdlformat.cpp for an example.*/
SkipObjects(int n,OBConversion * pConv)127 virtual int SkipObjects(int n, OBConversion* pConv)
128 {
129 return 0;
130 };
131
132 ////////////////////////////////////////////////////
133 /// Declarations for the "API" interface functions. Definitions are below
134 virtual bool ReadMolecule(OBBase* pOb, OBConversion* pConv);
135 virtual bool WriteMolecule(OBBase* pOb, OBConversion* pConv);
136
137 private:
138 /* Add declarations for any local function or member variables used.
139 Generally only a single instance of a format class is used. Keep this in
140 mind if you employ member variables. */
141 };
142 ////////////////////////////////////////////////////
143
144 //Make an instance of the format class
145 XXXFormat theXXXFormat;
146
147 /////////////////////////////////////////////////////////////////
148
ReadMolecule(OBBase * pOb,OBConversion * pConv)149 bool XXXFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv)
150 {
151 OBMol* pmol = pOb->CastAndClear<OBMol>();
152 if(pmol==nullptr)
153 return false;
154
155 istream& ifs = *pConv->GetInStream();
156
157 pmol->BeginModify();
158
159 /** Parse the input stream and use the OpenBabel API to populate the OBMol **/
160
161 // To use an input option
162 if(pConv->IsOption("s",OBConversion::INOPTIONS))
163 {
164 //Code for when -as is specified
165 }
166
167 /* If the molecule has other than 3D coordinates for its atoms, it
168 is necessary to set the dimension to 0, or 2 */
169 int dim;
170 pmol->SetDimension(dim);
171
172 pmol->EndModify();
173
174 /* For multi-molecule formats, leave the input stream at the start of the
175 next molecule, ready for this routine to be called again.
176
177 /* Return true if ok. Returning false means discard the OBMol and stop
178 converting, unless the -e option is set. With a multi-molecule inputstream
179 this will skip the current molecule and continue with the next, if SkipObjects()
180 has been defined. If it has not, and continuation after errors is still required,
181 it is necessary to leave the input stream at the beginning of next object when
182 returning false;*/
183 return true;
184 }
185
186 ////////////////////////////////////////////////////////////////
187
WriteMolecule(OBBase * pOb,OBConversion * pConv)188 bool XXXFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
189 {
190 OBMol* pmol = dynamic_cast<OBMol*>(pOb);
191 if(pmol==nullptr)
192 return false;
193
194 ostream& ofs = *pConv->GetOutStream();
195
196 /** Write the representation of the OBMol molecule to the output stream **/
197
198 //To use an output option
199 if(!pConv->IsOption("n")) //OBConversion::OUTOPTIONS is the default
200 ofs << "Title = " << pmol->GetTitle() << endl;
201 //or if the option has a parameter
202 int levels=0;
203 const char* p = pConv->IsOption("f");
204 if(p) //p==nullptr if f option absent
205 levels = atoi(p);
206
207 // To find out whether this is the first molecule to be output...
208 if(pConv->GetOutputIndex()==1)
209 ofs << "The contents of this file were derived from " << pConv->GetInFilename() << endl;
210 // ... or the last
211 if(!pConv->IsLast())
212 ofs << "$$$$" << endl;
213
214 return true; //or false to stop converting
215 }
216
217 } //namespace OpenBabel
218