abc18db29f29521c8e9f6466178e2bb4ad96c650
[alexxy/gromacs.git] / src / mdlib / gmx_qhop_xml.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 4.5
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2008, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14  
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * Groningen Machine for Chemical Simulation
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39
40 #include <string.h>
41 #include "gmx_fatal.h"
42 #include "smalloc.h"
43 #include "macros.h"
44 #include "futil.h"
45 #include "gmx_qhop_parm.h"
46
47 #ifdef HAVE_LIBXML2
48 #include <libxml/parser.h>
49 #include <libxml/tree.h>
50         
51 extern int xmlDoValidityCheckingDefaultValue;
52         
53 #define NN(x) (NULL != (x))
54
55 static const char *xmltypes[] = { 
56   NULL, 
57   "XML_ELEMENT_NODE",
58   "XML_ATTRIBUTE_NODE",
59   "XML_TEXT_NODE",
60   "XML_CDATA_SECTION_NODE",
61   "XML_ENTITY_REF_NODE",
62   "XML_ENTITY_NODE",
63   "XML_PI_NODE",
64   "XML_COMMENT_NODE",
65   "XML_DOCUMENT_NODE",
66   "XML_DOCUMENT_TYPE_NODE",
67   "XML_DOCUMENT_FRAG_NODE",
68   "XML_NOTATION_NODE",
69   "XML_HTML_DOCUMENT_NODE",
70   "XML_DTD_NODE",
71   "XML_ELEMENT_DECL",
72   "XML_ATTRIBUTE_DECL",
73   "XML_ENTITY_DECL",
74   "XML_NAMESPACE_DECL",
75   "XML_XINCLUDE_START",
76   "XML_XINCLUDE_END"
77 };
78 #define NXMLTYPES asize(xmltypes)
79         
80 enum { 
81   exmlQHOPS,
82   exmlQHOP, exmlDONOR, exmlACCEPTOR,
83   exmlPARAM, exmlNAME, exmlVALUE, 
84   exmlUNIT,
85   exmlNR 
86 };
87   
88 static const char *exml_names[exmlNR] = {
89   "qhops",
90   "qhop", "donor", "acceptor", "parameter", 
91   "name", "value", "unit" 
92 };
93
94 typedef struct {
95   int        nqh;
96   gmx_qhop_t *gqh;
97 } t_xmlrec;
98
99 static int find_elem(char *name,int nr,const char *names[])
100 {
101   int i;
102   
103   for(i=0; (i<nr); i++)
104     if (strcmp(name,names[i]) == 0) 
105       break;
106   if (i == nr)
107     gmx_fatal(FARGS,"Unknown element name %s",name);
108     
109   return i;
110 }
111
112 void add_xml_int(xmlNodePtr ptr,const char *name,int val)
113 {
114   xmlChar buf[32];
115   
116   sprintf((char *)buf,"%d",val);
117   if (xmlSetProp(ptr,(xmlChar *)name,buf) == 0)
118     gmx_fatal(FARGS,"Setting",(char *)name);
119 }
120
121 void add_xml_double(xmlNodePtr ptr,const char *name,double val)
122 {
123   xmlChar buf[32];
124   
125   sprintf((char *)buf,"%g",val);
126   if (xmlSetProp(ptr,(xmlChar *)name,buf) == 0)
127     gmx_fatal(FARGS,"Setting",(char *)name);
128 }
129
130 void add_xml_char(xmlNodePtr ptr,const char *name,char *val)
131 {
132   if (xmlSetProp(ptr,(xmlChar *)name,(xmlChar *)val) == 0)
133     gmx_fatal(FARGS,"Setting",(char *)name);
134 }
135
136 xmlNodePtr add_xml_child(xmlNodePtr parent,const char *type)
137 {
138   xmlNodePtr child;
139   
140   if ((child = xmlNewChild(parent,NULL,(xmlChar *)type,NULL)) == NULL)
141     gmx_fatal(FARGS,"Creating element",(char *)type);
142   
143   return child;
144 }
145
146 xmlNodePtr add_xml_comment(xmlDocPtr doc,
147                            xmlNodePtr prev,char *comment)
148 {
149   xmlNodePtr comm,ptr;
150   
151   if ((comm = xmlNewComment((xmlChar *)comment)) == NULL)
152     gmx_fatal(FARGS,"Creating doc comment element","");
153   ptr = prev;
154   while (ptr->next != NULL)
155     ptr=ptr->next;
156   ptr->next    = comm;
157   comm->prev   = ptr;
158   comm->doc    = doc;
159   
160   return comm;
161 }
162
163 static char *sp(int n, char buf[], int maxindent)
164 {
165   int i;
166   if(n>=maxindent)
167     n=maxindent-1;
168   
169   /* Don't indent more than maxindent characters */
170   for(i=0; (i<n); i++)
171     buf[i] = ' ';
172   buf[i] = '\0';
173   
174   return buf;
175 }
176
177 static void qhop_process_attr(FILE *fp,xmlAttrPtr attr,int parent,
178                               int elem,int indent,gmx_qhop_t qht)
179 {
180   char *attrname,*attrval;
181   char buf[100];
182   int  i,kkk,eprop;
183   char *xbuf[exmlNR];
184   
185   for(i=0; (i<exmlNR); i++)
186     xbuf[i] = NULL;
187   while (attr != NULL) {
188     attrname = (char *)attr->name;
189     attrval  = (char *)attr->children->content;
190     
191 #define atest(s) ((gmx_strcasecmp(attrname,s) == 0) && (attrval != NULL))
192     kkk = find_elem(attrname,exmlNR,exml_names);
193     if (attrval != NULL)
194       xbuf[kkk] = strdup(attrval);
195       
196     if (fp)
197       fprintf(fp,"%sProperty: '%s' Value: '%s'\n",sp(indent,buf,99),
198               attrname,attrval);
199     attr = attr->next;
200 #undef atest
201   }
202   
203   switch (elem) {
204   case exmlQHOP:
205     if (NN(xbuf[exmlDONOR]) && NN(xbuf[exmlACCEPTOR])) {
206       gmx_qhop_set_donor(qht,xbuf[exmlDONOR]);
207       gmx_qhop_set_acceptor(qht,xbuf[exmlACCEPTOR]);
208     }
209     break;
210   case exmlPARAM:
211     if (NN(xbuf[exmlNAME]) && NN(xbuf[exmlUNIT]) && NN(xbuf[exmlVALUE])) {
212       gmx_qhop_add_param(qht,xbuf[exmlNAME],xbuf[exmlVALUE],
213                          xbuf[exmlUNIT]);
214     }
215     break;
216   default:
217     break;
218   }
219   for(i=0; (i<exmlNR); i++)
220     if (NN(xbuf[i]))
221       sfree(xbuf[i]);
222 }
223
224 static void qhop_process_element(FILE *fp,xmlNodePtr tree,int parent,
225                                  int indent,t_xmlrec *xml)
226 {
227   int elem;
228   char buf[100];
229   
230   elem = find_elem((char *)tree->name,exmlNR,exml_names);
231   if (fp)
232     fprintf(fp,"%sElement node name %s\n",sp(indent,buf,99),
233             (char *)tree->name);
234   if (elem == exmlQHOP) {
235     xml->nqh++;
236     srenew(xml->gqh,xml->nqh);
237     xml->gqh[xml->nqh-1] = gmx_qhop_init();
238   }
239   if (elem != exmlQHOPS)
240     qhop_process_attr(fp,tree->properties,parent,
241                       elem,indent+2,xml->gqh[xml->nqh-1]);
242 }
243  
244 static void qhop_process_tree(FILE *fp,xmlNodePtr tree,int parent,
245                               int indent,t_xmlrec *xml)
246 {
247   char buf[100];
248   int  elem;
249   
250   while (tree != NULL) {
251     if (fp) {
252       if ((tree->type > 0) && (tree->type < NXMLTYPES))
253         fprintf(fp,"Node type %s encountered with name %s\n",
254                 xmltypes[tree->type],(char *)tree->name);
255       else
256         fprintf(fp,"Node type %d encountered\n",tree->type);
257     }
258     
259     switch (tree->type) {
260     case XML_ELEMENT_NODE:
261       qhop_process_element(fp,tree,parent,indent+2,xml);
262       
263       if (tree->children) {
264         elem = find_elem((char *)tree->name,exmlNR,exml_names);
265         qhop_process_tree(fp,tree->children,elem,indent+2,xml);
266       }
267       break;
268     default:
269       break;
270     }
271     tree = tree->next;
272   }
273 }
274
275 gmx_qhop_t *
276 gmx_qhops_read(char *fn,int *nqhop)
277 {
278   xmlDocPtr     doc;
279   int           i,npd;
280   t_xmlrec      *xml;
281   const char *db="qhops.dat";
282   gmx_bool fna=FALSE;
283   
284   xmlDoValidityCheckingDefaultValue = 0;
285   if (NULL == fn) 
286   {
287     fn = (char *)gmxlibfn(db);
288     fna=TRUE;
289   }
290   if ((doc = xmlParseFile(fn)) == NULL) {
291                 fprintf(stderr,"Reading XML file %s. Run a syntax checker such as nsgmls.",
292                                 fn);
293     exit(1);
294   }
295
296   snew(xml,1);
297   qhop_process_tree(NULL,doc->children,0,0,xml);
298   
299   xmlFreeDoc(doc);
300   if (fna)
301       sfree(fn);
302   
303   *nqhop = xml->nqh;
304   
305   return xml->gqh;
306 }
307
308 static void add_xml_qhop(xmlNodePtr parent,gmx_qhop_t qht)
309 {
310   xmlNodePtr ptr,child,grandchild,comp;
311   char   *name,*type,*value,*unit;
312   
313   ptr = add_xml_child(parent,exml_names[exmlQHOP]);
314   add_xml_char(ptr,exml_names[exmlDONOR],gmx_qhop_get_donor(qht));
315   add_xml_char(ptr,exml_names[exmlACCEPTOR],gmx_qhop_get_acceptor(qht));
316   
317   while (gmx_qhop_get_param(qht,&name,&value,&unit) == 1) {
318     child = add_xml_child(ptr,exml_names[exmlPARAM]);
319     add_xml_char(child,exml_names[exmlNAME],name);
320     add_xml_char(child,exml_names[exmlVALUE],value);
321     add_xml_char(child,exml_names[exmlUNIT],unit);
322     sfree(name);
323     sfree(value);
324     sfree(unit);
325   }
326 }
327
328 void gmx_qhops_write(char *fn,int nqhop,gmx_qhop_t qht[])
329 {
330   xmlDocPtr  doc;
331   xmlDtdPtr  dtd;
332   xmlNodePtr myroot;
333   int        i,nmt;
334   xmlChar    *libdtdname,*dtdname,*gmx;
335   
336   gmx        = (xmlChar *) "qhops";
337   dtdname    = (xmlChar *) "qhops.dtd";
338   libdtdname = dtdname;
339   
340   if ((doc = xmlNewDoc((xmlChar *)"1.0")) == NULL)
341     gmx_fatal(FARGS,"Creating XML document","");
342     
343   if ((dtd = xmlCreateIntSubset(doc,dtdname,libdtdname,dtdname)) == NULL)
344     gmx_fatal(FARGS,"Creating XML DTD","");
345     
346   if ((myroot = xmlNewDocNode(doc,NULL,gmx,NULL)) == NULL)
347     gmx_fatal(FARGS,"Creating root element","");
348   dtd->next = myroot;
349   myroot->prev = (xmlNodePtr) dtd;
350     
351   /* Add molecule definitions */
352   for(i=0; (i<nqhop); i++)
353     add_xml_qhop(myroot,qht[i]);
354
355   xmlSetDocCompressMode(doc,0);
356   xmlIndentTreeOutput = 1;
357   if (xmlSaveFormatFileEnc(fn,doc,"ISO-8859-1",2) == 0)
358     gmx_fatal(FARGS,"Saving file",fn);
359   xmlFreeDoc(doc);
360 }
361
362
363
364 #else
365
366 gmx_qhop_t gmx_qhops_read(char *fn,int *nqhop)
367 {
368   gmx_fatal(FARGS,"You need to configure the software with --with-xml for function gmx_qhops_read to work");
369   return NULL;
370 }
371
372 void gmx_qhops_write(char *fn,int nqhop,gmx_qhop_t qht)
373 {
374   gmx_fatal(FARGS,"You need to configure the software with --with-xml for function gmx_qhops_write to work");
375 }
376
377 #endif