source: XIOS/dev/dev_olga/src/extern/src_netcdf4/dapattr3.c @ 1022

Last change on this file since 1022 was 1022, checked in by mhnguyen, 7 years ago
File size: 10.7 KB
Line 
1/*********************************************************************
2 *   Copyright 1993, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *   $Header: /upc/share/CVS/netcdf-3/libncdap3/dapattr3.c,v 1.14 2009/12/03 03:42:38 dmh Exp $
5 *********************************************************************/
6
7#include "ncdap3.h"
8
9#define OCHECK(exp) if((ocstat = (exp))) goto done;
10
11/* Forward */
12static NCerror buildattribute(char*,nc_type,NClist*,NCattribute**);
13static int mergedas1(NCDAPCOMMON*, OCconnection, CDFnode* dds, OCobject das);
14static int isglobalname3(char* name);
15
16static NCerror
17buildattribute(char* name, nc_type ptype,
18               NClist* values, NCattribute** attp)
19{
20    NCerror ncstat = NC_NOERR;
21    NCattribute* att;
22
23    att = (NCattribute*)calloc(1,sizeof(NCattribute));
24    MEMCHECK(att,NC_ENOMEM);
25    att->name = nulldup(name);
26    att->etype = ptype;
27
28    att->values = values;
29
30    if(attp) *attp = att;
31
32    return THROW(ncstat);
33}
34
35/*
36Given a das attribute walk it to see if it
37has at least 1 actual attribute (no recursion)
38*/
39static int
40hasattribute3(OCconnection conn, OCobject dasnode)
41{
42    int i;
43    OCerror ocstat = OC_NOERR;
44    int tf = 0; /* assume false */
45    unsigned int nsubnodes;
46    OCtype ocsubtype;
47    OCobject* subnodes = NULL;
48
49    OCHECK(oc_inq_class(conn,dasnode,&ocsubtype));
50    if(ocsubtype == OC_Attribute) return 1; /* this is an attribute */
51    ASSERT((ocsubtype == OC_Attributeset));
52
53    OCHECK(oc_inq_nsubnodes(conn,dasnode,&nsubnodes));
54    OCHECK(oc_inq_subnodes(conn,dasnode,&subnodes));
55    for(i=0;i<nsubnodes;i++) {
56        OCobject subnode = subnodes[i];
57        OCHECK(oc_inq_class(conn,subnode,&ocsubtype));
58        if(ocsubtype == OC_Attribute) {tf=1; break;}
59    }
60done:
61    nullfree(subnodes);
62    return tf;
63}
64
65/*
66Duplicate the oc merge das and dds code, but
67modify to capture such things as "strlen" and "dimname".
68*/
69
70int
71dapmerge3(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCobject dasroot)
72{
73    unsigned int i,j;
74    NCerror ncerr = NC_NOERR;
75    OCerror ocstat = OC_NOERR;
76    OCconnection conn = nccomm->oc.conn;
77    unsigned int nsubnodes, nobjects;
78    OCobject* dasobjects = NULL;
79    NClist* dasglobals = nclistnew();
80    NClist* dasnodes = nclistnew();
81    NClist* dodsextra = nclistnew();
82    NClist* varnodes = nclistnew();
83    NClist* allddsnodes = ddsroot->tree->nodes;
84
85    if(ddsroot == NULL || dasroot == NULL) return NC_NOERR;
86
87    nobjects = oc_inq_nobjects(conn,dasroot);
88    dasobjects = oc_inq_objects(conn,dasroot);
89   
90    /* 1. collect all the relevant DAS nodes;
91          namely those that contain at least one
92          attribute value.
93          Simultaneously look for potential ambiguities
94          if found; complain but continue: result are indeterminate.
95          also collect globals and DODS_EXTRA separately.
96    */
97    for(i=0;i<nobjects;i++) {
98        OCobject das = dasobjects[i];
99        OCtype octype;
100        char* ocname = NULL;
101        int isglobal = 0;
102        int hasattributes = 0;
103
104        OCHECK(oc_inq_class(conn,das,&octype));
105        if(octype == OC_Attribute) continue; /* ignore these for now*/
106
107        OCHECK(oc_inq_name(conn,das,&ocname));
108        OCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes));
109
110        isglobal = (ocname == NULL ? 0 : isglobalname3(ocname));
111
112        /* catch DODS_EXTRA */
113        if(isglobal && ocname != NULL && strcmp(ocname,"DODS_EXTRA")==0) {
114            nclistpush(dodsextra,(ncelem)das);
115            nullfree(ocname);
116            continue;
117        }
118        if(ocname == NULL || isglobal) {
119            nclistpush(dasglobals,(ncelem)das);
120            nullfree(ocname);
121            continue;
122        }
123        hasattributes = hasattribute3(conn,das);
124        if(hasattributes) {
125            /* Look for previously collected nodes with same name*/
126            for(j=0;j<nclistlength(dasnodes);j++) {
127                OCobject das2 = (OCobject)nclistget(dasnodes,j);
128                char* ocname2;
129                OCHECK(oc_inq_name(conn,das2,&ocname2));
130                if(ocname2 == NULL || ocname == NULL) goto loop;
131                if(strcmp(ocname2,"DODS")==0) goto loop;
132                if(strcmp(ocname,ocname2)==0)
133                        nclog(NCLOGWARN,"nc_mergedas: potentially ambiguous DAS name: %s",ocname2);
134loop:
135                nullfree(ocname2);
136            }
137            nclistpush(dasnodes,(ncelem)das);
138        }
139        nullfree(ocname);
140    }
141
142    /* 2. collect all the leaf DDS nodes (of type NC_Primitive)*/
143    for(i=0;i<nclistlength(allddsnodes);i++) {
144        CDFnode* dds = (CDFnode*)nclistget(allddsnodes,i);
145        if(dds->nctype == NC_Primitive) nclistpush(varnodes,(ncelem)dds);
146    }
147
148    /* 3. For each das node, lncate matching DDS node(s) and attach
149          attributes to the DDS node(s).
150          Match means:
151          1. DAS->fullname :: DDS->fullname
152          2. DAS->name :: DDS->fullname (support DAS names with embedded '.'
153          3. DAS->name :: DDS->name
154          4. special case for DODS. Apply 1-3 on DODS parent.
155    */
156    for(i=0;i<nclistlength(dasnodes);i++) {
157        OCobject das = (OCobject)nclistget(dasnodes,i);
158        char* ocfullname = NULL;
159        char* ocbasename = NULL;
160
161        if(das == OCNULL) continue;
162        OCHECK(oc_inq_name(conn,das,&ocbasename));
163        if(strcmp(ocbasename,"DODS")==0) {
164            OCobject container;
165            OCHECK(oc_inq_container(conn,das,&container));
166            if(container == OCNULL) {
167                ASSERT(container != OCNULL);
168            }
169            ocfullname = makeocpathstring3(conn,container,".");
170        } else {
171            ocfullname = makeocpathstring3(conn,das,".");
172        }
173        for(j=0;j<nclistlength(varnodes);j++) {
174            CDFnode* dds = (CDFnode*)nclistget(varnodes,j);
175            char* ddsfullname = makecdfpathstring3(dds,".");
176            if(strcmp(ocfullname,ddsfullname)==0
177               || strcmp(ocbasename,ddsfullname)==0
178               || strcmp(ocbasename,dds->ocname)==0) {
179                mergedas1(nccomm,conn,dds,das);
180                /* remove from dasnodes list*/
181                nclistset(dasnodes,i,(ncelem)NULL);
182            }
183            nullfree(ddsfullname);
184        }
185        nullfree(ocfullname);
186        nullfree(ocbasename);
187    }
188
189    /* 4. Assign globals */
190    for(i=0;i<nclistlength(dasglobals);i++) {
191        OCobject das = (OCobject)nclistget(dasglobals,i);
192        mergedas1(nccomm,conn,ddsroot,das);
193    }
194
195    /* 5. Assign DOD_EXTRA */
196    for(i=0;i<nclistlength(dodsextra);i++) {
197        OCobject das = (OCobject)nclistget(dodsextra,i);
198        mergedas1(nccomm,conn,ddsroot,das);
199    }
200
201done: /* cleanup*/
202    nullfree(dasobjects);
203    nclistfree(dasglobals);
204    nclistfree(dasnodes);
205    nclistfree(dodsextra);
206    nclistfree(varnodes);
207    if(ocstat != OC_NOERR) ncerr = ocerrtoncerr(ocstat);
208    return THROW(ncerr);
209}
210
211static int
212mergedas1(NCDAPCOMMON* nccomm, OCconnection conn, CDFnode* dds, OCobject das)
213{
214    NCerror ncstat = NC_NOERR;
215    OCerror ocstat = OC_NOERR;
216    unsigned int i,j,k;
217    unsigned int nsubnodes;
218    OCobject* subnodes = NULL;
219    OCobject* dodsnodes = NULL;
220    unsigned int ndodsnodes;
221
222    if(dds == NULL || das == OCNULL) return NC_NOERR; /* nothing to do */
223    if(dds->attributes == NULL) dds->attributes = nclistnew();
224    /* assign the simple attributes in the das set to this dds node*/
225    OCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes));
226    OCHECK(oc_inq_subnodes(conn,das,&subnodes));
227    for(i=0;i<nsubnodes;i++) {
228        OCobject attnode = subnodes[i];
229        OCtype octype, ocetype;
230        char* ocname = NULL;
231        unsigned int ocnvalues;
232        OCHECK(oc_inq_name(conn,attnode,&ocname));     
233        OCHECK(oc_inq_class(conn,attnode,&octype));
234        if(octype == OC_Attribute) {
235            NCattribute* att = NULL;
236            NClist* stringvalues;
237            OCHECK(oc_inq_primtype(conn,attnode,&ocetype));     
238            OCHECK(oc_inq_dasattr_nvalues(conn,attnode,&ocnvalues));
239            stringvalues = nclistnew();
240            for(j=0;j<ocnvalues;j++) {
241                char* stringval;
242                OCHECK(oc_inq_dasattr(conn,attnode,j,&ocetype,&stringval));
243                nclistpush(stringvalues,(ncelem)stringval);
244            }
245            ncstat = buildattribute(ocname,
246                                    octypetonc(ocetype),
247                                    stringvalues,
248                                    &att);                             
249            if(ncstat) goto done;
250            nclistpush(dds->attributes,(ncelem)att);
251        } else if(octype == OC_Attributeset
252                  && (strcmp(ocname,"DODS")==0
253                      || strcmp(ocname,"DODS_EXTRA")==0)) {
254            /* Turn the DODS special attributes into into
255               special attributes for dds node */
256            OCHECK(oc_inq_nsubnodes(conn,attnode,&ndodsnodes));
257            OCHECK(oc_inq_subnodes(conn,attnode,&dodsnodes));
258            for(j=0;j<ndodsnodes;j++) {
259                char* dodsname = NULL;
260                char newname[4096];
261                OCobject attnode = dodsnodes[j];
262                NCattribute* att = NULL;
263                NClist* stringvalues;
264                OCHECK(oc_inq_class(conn,attnode,&octype));
265                if(octype != OC_Attribute) continue;
266                OCHECK(oc_inq_primtype(conn,attnode,&ocetype)); 
267                OCHECK(oc_inq_dasattr_nvalues(conn,attnode,&ocnvalues));
268                stringvalues = nclistnew();
269                for(k=0;k<ocnvalues;k++) {
270                    char* stringval;
271                    OCHECK(oc_inq_dasattr(conn,attnode,k,&ocetype,&stringval));
272                    nclistpush(stringvalues,(ncelem)stringval);
273                }
274                OCHECK(oc_inq_name(conn,attnode,&dodsname));
275                /* Compute new special name */
276                strcpy(newname,"_DODS_");
277                strcat(newname,dodsname);
278                ncstat = buildattribute(newname,
279                                        octypetonc(ocetype),
280                                        stringvalues,
281                                        &att);                         
282                if(ncstat) goto done;
283                att->invisible = 1;
284                nclistpush(dds->attributes,(ncelem)att);
285
286                /* Define extra semantics associated with DODS and DODS_EXTRA attribute */
287                if(strcmp(dodsname,"strlen")==0) {
288                    unsigned int maxstrlen = 0;
289                    if(nclistlength(stringvalues) > 0) {
290                        char* stringval = (char*)nclistget(stringvalues,0);
291                        if(0==sscanf(stringval,"%u",&maxstrlen)) maxstrlen = 0;
292                    }
293                    dds->dodsspecial.maxstrlen = maxstrlen;
294#ifdef DEBUG
295fprintf(stderr,"%s.maxstrlen=%d\n",dds->ocname,(int)dds->dodsspecial.maxstrlen);
296#endif
297                } else if(strcmp(dodsname,"dimName")==0) {
298                    if(nclistlength(stringvalues) > 0) {
299                        char* stringval = (char*)nclistget(stringvalues,0);
300                        dds->dodsspecial.dimname = nulldup(stringval);
301#ifdef DEBUG
302fprintf(stderr,"%s.dimname=%s\n",dds->ocname,dds->dodsspecial.dimname);
303#endif
304                    } else dds->dodsspecial.dimname = NULL;
305                } else if(strcmp(dodsname,"Unlimited_Dimension")==0) {
306                    if(nccomm->cdf.recorddimname != NULL) {
307                        nclog(NCLOGWARN,"Duplicate DODS_EXTRA:Unlimited_Dimension specifications");
308                    } else if(nclistlength(stringvalues) > 0) {
309                        char* stringval = (char*)nclistget(stringvalues,0);
310                        nccomm->cdf.recorddimname = nulldup(stringval);
311#ifdef DEBUG
312fprintf(stderr,"%s.Unlimited_Dimension=%s\n",dds->ocname,nccomm->cdf.recorddimname);
313#endif
314                    }
315                } /* else ignore */
316                nullfree(dodsname);
317            }
318            nullfree(dodsnodes);
319        }
320        nullfree(ocname);
321    }
322
323done:
324    nullfree(subnodes);
325    if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat);
326    return THROW(ncstat);
327}
328
329static int
330isglobalname3(char* name)
331{
332    int len = strlen(name);
333    int glen = strlen("global");
334    char* p;
335    if(len < glen) return 0;
336    p = name + (len - glen);
337    if(strcasecmp(p,"global") != 0)
338        return 0;
339    return 1;
340}
341
Note: See TracBrowser for help on using the repository browser.