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