1/*********************************************************************
2 *   Copyright 1993, UCAR/Unidata
3 *   See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 *********************************************************************/
5
6#include "ncdap.h"
7
8#define OCCHECK(exp) if((ocstat = (exp))) {THROWCHK(ocstat); goto done;}
9
10/* Forward */
11static NCerror buildattribute(char*,nc_type,size_t,char**,NCattribute**);
12
13/*
14Invoke oc_merge_das and then extract special
15attributes such as "strlen" and "dimname"
16and stuff from DODS_EXTRA.
17*/
18int
19dapmerge(NCDAPCOMMONnccommCDFnodeddsrootOCddsnode dasroot)
20{
21    int i,j;
22    NCerror ncstat = NC_NOERR;
23    OCerror ocstat = OC_NOERR;
24    NClistallnodes;
25    OClink conn;
26    char* ocname = NULL;
27    char** values = NULL;
28    conn = nccomm->oc.conn;
29
30    if(ddsroot == NULL || dasroot == NULL)
31 return NC_NOERR;
32    /* Merge the das tree onto the dds tree */
33    ocstat = oc_merge_das(nccomm->oc.conn,dasroot,ddsroot->ocnode);
34    if(ocstat != OC_NOERR) goto done;
35
36    /* Create attributes on CDFnodes */
37    allnodes = ddsroot->tree->nodes;
38    for(i=0;i<nclistlength(allnodes);i++) {
39 CDFnodenode = (CDFnode*)nclistget(allnodes,i);
40 OCddsnode ocnode = node->ocnode;
41 size_t attrcount;
42 OCtype ocetype;
43
44 OCCHECK(oc_dds_attr_count(conn,ocnode,&attrcount));
45 for(j=0;j<attrcount;j++) {
46     size_t nvalues;
47
48     NCattributeatt = NULL;
49
50     if(ocname != NULL) {
51       free(ocname); ocname = NULL;
52     } /* from last loop */
53
54     OCCHECK(oc_dds_attr(conn,ocnode,j,&ocname,&ocetype,&nvalues,NULL));
55     if(nvalues > 0) {
56         values = (char**)malloc(sizeof(char*)*nvalues);
57 if(values == NULL) {ncstat = NC_ENOMEM; goto done;}
58         OCCHECK(oc_dds_attr(conn,ocnode,j,NULL,NULL,NULL,values));
59     }
60     ncstat = buildattribute(ocname,octypetonc(ocetype),nvalues,values,&att);
61     if(ncstat != NC_NOERR) goto done;
62     if(node->attributes == NULL)
63 node->attributes = nclistnew();
64     nclistpush(node->attributes,(void*)att);
65     if(strncmp(ocname,"DODS",strlen("DODS"))==0) {
66 att->invisible = 1;
67         /* Define extra semantics associated with
68                   DODS and DODS_EXTRA attributes */
69 if(strcmp(ocname,"DODS.strlen")==0
70    || strcmp(ocname,"DODS_EXTRA.strlen")==0) {
71     unsigned int maxstrlen = 0;
72     if(values != NULL) {
73 if(0==sscanf(values[0],"%u",&maxstrlen))
74     maxstrlen = 0;
75     }
76     node->dodsspecial.maxstrlen = maxstrlen;
77#ifdef DEBUG
78fprintf(stderr,"%s.maxstrlen=%d\n",node->ocname,(int)node->dodsspecial.maxstrlen);
79#endif
80 } else if(strcmp(ocname,"DODS.dimName")==0
81    || strcmp(ocname,"DODS_EXTRA.dimName")==0) {
82     if(values != NULL) {
83         node->dodsspecial.dimname = nulldup(values[0]);
84#ifdef DEBUG
85fprintf(stderr,"%s.dimname=%s\n",node->ocname,node->dodsspecial.dimname);
86#endif
87     } else node->dodsspecial.dimname = NULL;
88 } else if(strcmp(ocname,"DODS.Unlimited_Dimension")==0
89    || strcmp(ocname,"DODS_EXTRA.Unlimited_Dimension")==0) {
90     if(values != NULL) {
91         if(nccomm->cdf.recorddimname != NULL)
92             nclog(NCLOGWARN,"Duplicate DODS_EXTRA:Unlimited_Dimension specifications");
93 else
94             nccomm->cdf.recorddimname = nulldup(values[0]);
95#ifdef DEBUG
96fprintf(stderr,"%s.Unlimited_Dimension=%s\n",node->ocname,nccomm->cdf.recorddimname);
97#endif
98     }
99
100 }
101     }
102     /* clean up */
103     if(values) {
104 oc_reclaim_strings(nvalues,values);
105 free(values);
106 values = NULL;
107     }
108 }
109    }
110
111done:
112    if(values != NULL) free(values);
113    if(ocname != NULL) free(ocname);
114    if(ocstat != OC_NOERRncstat = ocerrtoncerr(ocstat);
115    return THROW(ncstat);
116}
117
118/* Build an NCattribute */
119static NCerror
120buildattribute(char* namenc_type ptype,
121               size_t nvalues, char** valuesNCattribute** attp)
122{
123    int i;
124    NCerror ncstat = NC_NOERR;
125    NCattributeatt = NULL;
126
127    att = (NCattribute*)calloc(1,sizeof(NCattribute));
128    MEMCHECK(att,NC_ENOMEM);
129    att->name = nulldup(name);
130    att->etype = ptype;
131
132    att->values = nclistnew();
133    for(i=0;i<nvalues;i++)
134 nclistpush(att->values,(void*)nulldup(values[i]));
135
136    if(attp) *attp = att;
137    else
138      free(att);
139
140    return THROW(ncstat);
141}
142
143#if 0
144/*
145Given a das attribute walk it to see if it
146has at least 1 actual attribute (no recursion)
147*/
148static int
149hasattribute(OClink connOCdasnode dasnode)
150{
151    int i;
152    OCerror ocstat = OC_NOERR;
153    int tf = 0; /* assume false */
154    OCtype ocsubtype;
155    NClistsubnodes = nclistnew();
156
157    OCCHECK(oc_dds_octype(conn,dasnode,&ocsubtype));
158    if(ocsubtype == OC_Attribute) return 1; /* this is an attribute */
159    ASSERT((ocsubtype == OC_Attributeset));
160
161    OCCHECK(collect_subnodes(conn,dasnode,subnodes));
162    for(i=0;i<nclistlength(subnodes);i++) {
163        OCdasnode subnode = (OCdasnode)nclistget(subnodes,i);
164        OCCHECK(oc_dds_class(conn,subnode,&ocsubtype));
165 if(ocsubtype == OC_Attribute) {tf=1; break;}
166    }
167done:
168    nclistfree(subnodes);
169    return tf;
170}
171
172int
173dapmerge(NCDAPCOMMONnccommCDFnodeddsrootOCddsnode dasroot)
174{
175    unsigned int i,j;
176    NCerror ncerr = NC_NOERR;
177    OCerror ocstat = OC_NOERR;
178    OClink conn = nccomm->oc.conn;
179    size_t nsubnodes;
180    NClistdasglobals = nclistnew();
181    NClistdasnodes = nclistnew();
182    NClistdodsextra = nclistnew();
183    NClistvarnodes = nclistnew();
184    NClistalldasnodes = nclistnew();
185
186    if(ddsroot == NULL || dasroot == NULL) return NC_NOERR;
187
188    ocstat = collect_alldasnodes(conn,dasroot,alldasnodes);
189
190    /* 1. collect all the relevant DAS nodes;
191          namely those that contain at least one
192          attribute value.
193          Simultaneously look for potential ambiguities
194          if found; complain but continue: result are indeterminate.
195          also collect globals and DODS_EXTRA separately.
196    */
197    for(i=0;i<nclistlength(alldasnodes);i++) {
198 OCddsnode das = (OCddsnode)nclistget(alldasnodes,i);
199 OCtype octype;
200        char* ocname = NULL;
201 int isglobal = 0;
202 int hasattributes = 0;
203
204        OCCHECK(oc_dds_class(conn,das,&octype));
205 if(octype == OC_Attribute) continue; /* ignore these for now*/
206
207        OCCHECK(oc_dds_name(conn,das,&ocname));
208 OCCHECK(oc_dds_nsubnodes(conn,das,&nsubnodes));
209
210 isglobal = (ocname == NULL ? 0 : isglobalname(ocname));
211
212 /* catch DODS_EXTRA */
213 if(isglobal && ocname != NULL && strcmp(ocname,"DODS_EXTRA")==0) {
214     nclistpush(dodsextra,(void*)das);
215     nullfree(ocname);
216     continue;
217 }
218 if(ocname == NULL || isglobal) {
219            nclistpush(dasglobals,(void*)das);
220     nullfree(ocname);
221     continue;
222 }
223 hasattributes = hasattribute(conn,das);
224 if(hasattributes) {
225     /* Look for previously collected nodes with same name*/
226            for(j=0;j<nclistlength(dasnodes);j++) {
227         OCddsnode das2 = (OCddsnode)nclistget(dasnodes,j);
228 char* ocname2;
229         OCCHECK(oc_dds_name(conn,das2,&ocname2));
230 if(ocname2 == NULL || ocname == NULL) goto loop;
231 if(strcmp(ocname2,"DODS")==0) goto loop;
232         if(strcmp(ocname,ocname2)==0)
233         nclog(NCLOGWARN,"nc_mergedas: potentially ambiguous DAS name: %s",ocname2);
234loop:
235 nullfree(ocname2);
236     }
237     nclistpush(dasnodes,(void*)das);
238 }
239 nullfree(ocname);
240    }
241
242    /* 2. collect all the leaf DDS nodes (of type NC_Atomic)*/
243    ocstat = collect_leaves(link,ddsroot,varnodes);
244
245    /* 3. For each das node, locate matching DDS node(s) and attach
246          attributes to the DDS node(s).
247          Match means:
248          1. DAS->fullname :: DDS->fullname
249          2. DAS->name :: DDS->fullname (support DAS names with embedded '.'
250          3. DAS->name :: DDS->name
251   4. special case for DODS. Apply 1-3 on DODS parent.
252    */
253    for(i=0;i<nclistlength(dasnodes);i++) {
254 OCddsnode das = (OCddsnode)nclistget(dasnodes,i);
255 char* ocfullname = NULL;
256 char* ocbasename = NULL;
257
258 if(das == NULL) continue;
259 OCCHECK(oc_dds_name(conn,das,&ocbasename));
260 if(strcmp(ocbasename,"DODS")==0) {
261     OCddsnode container;
262        OCCHECK(oc_dds_container(conn,das,&container));
263            ASSERT(container != NULL);
264     ocfullname = makeocpathstring(conn,container,".");
265 } else {
266     ocfullname = makeocpathstring(conn,das,".");
267 }
268        for(j=0;j<nclistlength(varnodes);j++) {
269     CDFnodedds = (CDFnode*)nclistget(varnodes,j);
270     char* ddsfullname = makecdfpathstring(dds,".");
271     if(strcmp(ocfullname,ddsfullname)==0
272        || strcmp(ocbasename,ddsfullname)==0
273        || strcmp(ocbasename,dds->ocname)==0) {
274 mergedas1(nccomm,conn,dds,das);
275 /* remove from dasnodes list*/
276 nclistset(dasnodes,i,(void*)NULL);
277     }
278     nullfree(ddsfullname);
279 }
280 nullfree(ocfullname);
281 nullfree(ocbasename);
282    }
283
284    /* 4. Assign globals */
285    for(i=0;i<nclistlength(dasglobals);i++) {
286 OCddsnode das = (OCddsnode)nclistget(dasglobals,i);
287 mergedas1(nccomm,conn,ddsroot,das);
288    }
289
290    /* 5. Assign DOD_EXTRA */
291    for(i=0;i<nclistlength(dodsextra);i++) {
292 OCddsnode das = (OCddsnode)nclistget(dodsextra,i);
293 mergedas1(nccomm,conn,ddsroot,das);
294    }
295
296done: /* cleanup*/
297    nclistfree(dasglobals);
298    nclistfree(dasnodes);
299    nclistfree(alldasnodes);
300    nclistfree(dodsextra);
301    nclistfree(varnodes);
302    if(ocstat != OC_NOERR)
303 ncerr = ocerrtoncerr(ocstat);
304    return THROW(ncerr);
305}
306
307static int
308mergedas1(NCDAPCOMMONnccommOClink connCDFnodeddsOCddsnode das)
309{
310    NCerror ncstat = NC_NOERR;
311    OCerror ocstat = OC_NOERR;
312    unsigned int i,j,k;
313    unsigned int nsubnodes;
314    OCobjectsubnodes = NULL;
315    OCobjectdodsnodes = NULL;
316    unsigned int ndodsnodes;
317
318    if(dds == NULL || das == OCNULL) return NC_NOERR; /* nothing to do */
319    if(dds->attributes == NULLdds->attributes = nclistnew();
320    /* assign the simple attributes in the das set to this dds node*/
321    OCCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes));
322    OCCHECK(oc_inq_subnodes(conn,das,&subnodes));
323    for(i=0;i<nsubnodes;i++) {
324 OCobject attnode = subnodes[i];
325 OCtype octypeocetype;
326 char* ocname = NULL;
327 unsigned int ocnvalues;
328        OCCHECK(oc_inq_name(conn,attnode,&ocname));
329        OCCHECK(oc_inq_class(conn,attnode,&octype));
330 if(octype == OC_Attribute) {
331     NCattributeatt = NULL;
332     NCliststringvalues;
333            OCCHECK(oc_inq_primtype(conn,attnode,&ocetype));
334     OCCHECK(oc_inq_dasattr_nvalues(conn,attnode,&ocnvalues));
335     stringvalues = nclistnew();
336     for(j=0;j<ocnvalues;j++) {
337 char* stringval;
338         OCCHECK(oc_inq_dasattr(conn,attnode,j,&ocetype,&stringval));
339         nclistpush(stringvalues,(void*)stringval);
340     }
341     ncstat = buildattribute(ocname,
342     octypetonc(ocetype),
343     stringvalues,
344     &att);
345     if(ncstat) goto done;
346            nclistpush(dds->attributes,(void*)att);
347 } else if(octype == OC_Attributeset
348   && (strcmp(ocname,"DODS")==0
349       || strcmp(ocname,"DODS_EXTRA")==0)) {
350     /* Turn the DODS special attributes into into
351               special attributes for dds node */
352     OCCHECK(oc_inq_nsubnodes(conn,attnode,&ndodsnodes));
353     OCCHECK(oc_inq_subnodes(conn,attnode,&dodsnodes));
354     for(j=0;j<ndodsnodes;j++) {
355 char* dodsname = NULL;
356 char newname[4096];
357         OCobject attnode = dodsnodes[j];
358         NCattributeatt = NULL;
359         NCliststringvalues;
360         OCCHECK(oc_inq_class(conn,attnode,&octype));
361 if(octype != OC_Attribute) continue;
362                OCCHECK(oc_inq_primtype(conn,attnode,&ocetype));
363         OCCHECK(oc_inq_dasattr_nvalues(conn,attnode,&ocnvalues));
364         stringvalues = nclistnew();
365         for(k=0;k<ocnvalues;k++) {
366     char* stringval;
367             OCCHECK(oc_inq_dasattr(conn,attnode,k,&ocetype,&stringval));
368             nclistpush(stringvalues,(void*)stringval);
369 }
370         OCCHECK(oc_inq_name(conn,attnode,&dodsname));
371 /* Compute new special name */
372 strcpy(newname,"_DODS_");
373 strcat(newname,dodsname);
374         ncstat = buildattribute(newname,
375         octypetonc(ocetype),
376         stringvalues,
377         &att);
378 if(ncstat) goto done;
379 att->invisible = 1;
380             nclistpush(dds->attributes,(void*)att);
381
382 /* Define extra semantics associated with DODS and DODS_EXTRA attribute */
383 if(strcmp(dodsname,"strlen")==0) {
384     unsigned int maxstrlen = 0;
385     if(nclistlength(stringvalues) > 0) {
386         char* stringval = (char*)nclistget(stringvalues,0);
387 if(0==sscanf(stringval,"%u",&maxstrlen)) maxstrlen = 0;
388     }
389     dds->dodsspecial.maxstrlen = maxstrlen;
390#ifdef DEBUG
391fprintf(stderr,"%s.maxstrlen=%d\n",dds->ocname,(int)dds->dodsspecial.maxstrlen);
392#endif
393 } else if(strcmp(dodsname,"dimName")==0) {
394     if(nclistlength(stringvalues) > 0) {
395         char* stringval = (char*)nclistget(stringvalues,0);
396         dds->dodsspecial.dimname = nulldup(stringval);
397#ifdef DEBUG
398fprintf(stderr,"%s.dimname=%s\n",dds->ocname,dds->dodsspecial.dimname);
399#endif
400     } else dds->dodsspecial.dimname = NULL;
401 } else if(strcmp(dodsname,"Unlimited_Dimension")==0) {
402     if(nccomm->cdf.recorddimname != NULL) {
403         nclog(NCLOGWARN,"Duplicate DODS_EXTRA:Unlimited_Dimension specifications");
404     } else if(nclistlength(stringvalues) > 0) {
405         char* stringval = (char*)nclistget(stringvalues,0);
406 nccomm->cdf.recorddimname = nulldup(stringval);
407#ifdef DEBUG
408fprintf(stderr,"%s.Unlimited_Dimension=%s\n",dds->ocname,nccomm->cdf.recorddimname);
409#endif
410     }
411 } /* else ignore */
412         nullfree(dodsname);
413     }
414     nullfree(dodsnodes);
415 }
416        nullfree(ocname);
417    }
418
419done:
420    nullfree(subnodes);
421    if(ocstat != OC_NOERRncstat = ocerrtoncerr(ocstat);
422    return THROW(ncstat);
423}
424
425static int
426isglobalname(char* name)
427{
428    int len = strlen(name);
429    int glen = strlen("global");
430    char* p;
431    if(len < glen) return 0;
432    p = name + (len - glen);
433    if(strcasecmp(p,"global") != 0)
434 return 0;
435    return 1;
436}
437
438
439static OCerror
440collect_alldasnodes(OClink linkOCddsnode dasnodeNClistalldasnodes)
441{
442    size_t nsubnodes,i;
443    OCerror ocstat = OC_NOERR;
444    nclistpush(alldasnodes,(void*)dasnode);
445    ocstat = oc_dds_nsubnodes(link,dasnode,&nsubnodes);
446    if(ocstat != OC_NOERR) goto done;
447    for(i=0;i<nsubnodes;i++) {
448 OCddsnode subnode;
449 ocstat = oc_dds_ithsubnode(link,dasnode,i,&subnode);
450        if(ocstat != OC_NOERR) goto done;
451 ocstat = collect_alldasnodes(link,subnode,alldasnodes);
452        if(ocstat != OC_NOERR) goto done;
453    }
454
455done:
456    return ocstat;
457}
458
459static OCerror
460collect_leaves(OClink linkOCddsnode ddsnodeNClistleaves)
461{
462    size_t nsubnodes,i;
463    OCerror ocstat = OC_NOERR;
464    OCtype octype;
465    ocstat = oc_dds_octype(link,ddsnode,&octype);
466    if(ocstat != OC_NOERR) goto done;
467    if(octype == OC_Atomic) {
468        nclistpush(leaves,(void*)ddsnode);
469    } else {
470        ocstat = oc_dds_nsubnodes(link,ddsnode,&nsubnodes);
471        if(ocstat != OC_NOERR) goto done;
472        for(i=0;i<nsubnodes;i++) {
473     OCddsnode subnode;
474     ocstat = oc_dds_ithsubnode(link,ddsnode,i,&subnode);
475            if(ocstat != OC_NOERR) goto done;
476     ocstat = collect_leaves(link,subnode,leaves);
477            if(ocstat != OC_NOERR) goto done;
478 }
479    }
480
481done:
482    return ocstat;
483}
484
485static OCerror
486collect_subnodes(OClink linkOCddsnode ddsnodeNClistsubnodes)
487{
488    size_t nsubnodes,i;
489    OCerror ocstat = OC_NOERR;
490    ocstat = oc_dds_nsubnodes(link,ddsnode,&nsubnodes);
491    if(ocstat != OC_NOERR) goto done;
492    for(i=0;i<nsubnodes;i++) {
493        OCddsnode subnode;
494 ocstat = oc_dds_ithsubnode(link,ddsnode,i,&subnode);
495        if(ocstat != OC_NOERR) goto done;
496 nclistpush(subnodes,(void*)subnode);
497    }
498
499done:
500    return ocstat;
501}
502#endif /*0*/


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed