static OCerror collect_leaves(OClink link, OCddsnode ddsnode, NClist* leaves) { size_t nsubnodes,i; OCerror ocstat = OC_NOERR; OCtype octype; ocstat = oc_dds_octype(link,ddsnode,&octype); if(ocstat != OC_NOERR) goto done; if(octype == OC_Atomic) { nclistpush(leaves,(void*)ddsnode); } else { ocstat = oc_dds_nsubnodes(link,ddsnode,&nsubnodes); if(ocstat != OC_NOERR) goto done; for(i=0;i<nsubnodes;i++) { OCddsnode subnode; ocstat = oc_dds_ithsubnode(link,ddsnode,i,&subnode); if(ocstat != OC_NOERR) goto done; ocstat = collect_leaves(link,subnode,leaves); if(ocstat != OC_NOERR) goto done; } } done: return ocstat; }
static OCerror collect_subnodes(OClink link, OCddsnode ddsnode, NClist* subnodes) { size_t nsubnodes,i; OCerror ocstat = OC_NOERR; ocstat = oc_dds_nsubnodes(link,ddsnode,&nsubnodes); if(ocstat != OC_NOERR) goto done; for(i=0;i<nsubnodes;i++) { OCddsnode subnode; ocstat = oc_dds_ithsubnode(link,ddsnode,i,&subnode); if(ocstat != OC_NOERR) goto done; nclistpush(subnodes,(void*)subnode); } done: return ocstat; }
int dapmerge3(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCddsnode dasroot) { unsigned int i,j; NCerror ncerr = NC_NOERR; OCerror ocstat = OC_NOERR; OClink conn = nccomm->oc.conn; size_t nsubnodes; NClist* dasglobals = nclistnew(); NClist* dasnodes = nclistnew(); NClist* dodsextra = nclistnew(); NClist* varnodes = nclistnew(); NClist* alldasnodes = nclistnew(); if(ddsroot == NULL || dasroot == NULL) return NC_NOERR; ocstat = collect_alldasnodes(conn,dasroot,alldasnodes); /* 1. collect all the relevant DAS nodes; namely those that contain at least one attribute value. Simultaneously look for potential ambiguities if found; complain but continue: result are indeterminate. also collect globals and DODS_EXTRA separately. */ for(i=0;i<nclistlength(alldasnodes);i++) { OCddsnode das = (OCddsnode)nclistget(alldasnodes,i); OCtype octype; char* ocname = NULL; int isglobal = 0; int hasattributes = 0; OCCHECK(oc_dds_class(conn,das,&octype)); if(octype == OC_Attribute) continue; /* ignore these for now*/ OCCHECK(oc_dds_name(conn,das,&ocname)); OCCHECK(oc_dds_nsubnodes(conn,das,&nsubnodes)); isglobal = (ocname == NULL ? 0 : isglobalname3(ocname)); /* catch DODS_EXTRA */ if(isglobal && ocname != NULL && strcmp(ocname,"DODS_EXTRA")==0) { nclistpush(dodsextra,(void*)das); nullfree(ocname); continue; } if(ocname == NULL || isglobal) { nclistpush(dasglobals,(void*)das); nullfree(ocname); continue; } hasattributes = hasattribute3(conn,das); if(hasattributes) { /* Look for previously collected nodes with same name*/ for(j=0;j<nclistlength(dasnodes);j++) { OCddsnode das2 = (OCddsnode)nclistget(dasnodes,j); char* ocname2; OCCHECK(oc_dds_name(conn,das2,&ocname2)); if(ocname2 == NULL || ocname == NULL) goto loop; if(strcmp(ocname2,"DODS")==0) goto loop; if(strcmp(ocname,ocname2)==0) nclog(NCLOGWARN,"nc_mergedas: potentially ambiguous DAS name: %s",ocname2); loop: nullfree(ocname2); } nclistpush(dasnodes,(void*)das); } nullfree(ocname); } /* 2. collect all the leaf DDS nodes (of type NC_Atomic)*/ ocstat = collect_leaves(link,ddsroot,varnodes); /* 3. For each das node, locate matching DDS node(s) and attach attributes to the DDS node(s). Match means: 1. DAS->fullname :: DDS->fullname 2. DAS->name :: DDS->fullname (support DAS names with embedded '.' 3. DAS->name :: DDS->name 4. special case for DODS. Apply 1-3 on DODS parent. */ for(i=0;i<nclistlength(dasnodes);i++) { OCddsnode das = (OCddsnode)nclistget(dasnodes,i); char* ocfullname = NULL; char* ocbasename = NULL; if(das == NULL) continue; OCCHECK(oc_dds_name(conn,das,&ocbasename)); if(strcmp(ocbasename,"DODS")==0) { OCddsnode container; OCCHECK(oc_dds_container(conn,das,&container)); ASSERT(container != NULL); ocfullname = makeocpathstring3(conn,container,"."); } else { ocfullname = makeocpathstring3(conn,das,"."); } for(j=0;j<nclistlength(varnodes);j++) { CDFnode* dds = (CDFnode*)nclistget(varnodes,j); char* ddsfullname = makecdfpathstring3(dds,"."); if(strcmp(ocfullname,ddsfullname)==0 || strcmp(ocbasename,ddsfullname)==0 || strcmp(ocbasename,dds->ocname)==0) { mergedas1(nccomm,conn,dds,das); /* remove from dasnodes list*/ nclistset(dasnodes,i,(void*)NULL); } nullfree(ddsfullname); } nullfree(ocfullname); nullfree(ocbasename); } /* 4. Assign globals */ for(i=0;i<nclistlength(dasglobals);i++) { OCddsnode das = (OCddsnode)nclistget(dasglobals,i); mergedas1(nccomm,conn,ddsroot,das); } /* 5. Assign DOD_EXTRA */ for(i=0;i<nclistlength(dodsextra);i++) { OCddsnode das = (OCddsnode)nclistget(dodsextra,i); mergedas1(nccomm,conn,ddsroot,das); } done: /* cleanup*/ nclistfree(dasglobals); nclistfree(dasnodes); nclistfree(alldasnodes); nclistfree(dodsextra); nclistfree(varnodes); if(ocstat != OC_NOERR) ncerr = ocerrtoncerr(ocstat); return THROW(ncerr); }
static NCerror buildcdftreer(NCDAPCOMMON* nccomm, OCddsnode ocnode, CDFnode* container, CDFtree* tree, CDFnode** cdfnodep) { size_t i,ocrank,ocnsubnodes; OCtype octype; OCtype ocatomtype; char* ocname = NULL; NCerror ncerr = NC_NOERR; CDFnode* cdfnode = NULL; oc_dds_class(nccomm->oc.conn,ocnode,&octype); if(octype == OC_Atomic) oc_dds_atomictype(nccomm->oc.conn,ocnode,&ocatomtype); else ocatomtype = OC_NAT; oc_dds_name(nccomm->oc.conn,ocnode,&ocname); oc_dds_rank(nccomm->oc.conn,ocnode,&ocrank); oc_dds_nsubnodes(nccomm->oc.conn,ocnode,&ocnsubnodes); #ifdef DEBUG1 if(ocatomtype == OC_NAT) fprintf(stderr,"buildcdftree: connect: %s %s\n",oc_typetostring(octype),ocname); else fprintf(stderr,"buildcdftree: connect: %s %s\n",oc_typetostring(ocatomtype),ocname); #endif switch (octype) { case OC_Dataset: cdfnode = makecdfnode(nccomm,ocname,octype,ocnode,container); nclistpush(tree->nodes,(void*)cdfnode); tree->root = cdfnode; cdfnode->tree = tree; break; case OC_Grid: case OC_Structure: case OC_Sequence: cdfnode = makecdfnode(nccomm,ocname,octype,ocnode,container); nclistpush(tree->nodes,(void*)cdfnode); #if 0 if(tree->root == NULL) { tree->root = cdfnode; cdfnode->tree = tree; } #endif break; case OC_Atomic: cdfnode = makecdfnode(nccomm,ocname,octype,ocnode,container); nclistpush(tree->nodes,(void*)cdfnode); #if 0 if(tree->root == NULL) { tree->root = cdfnode; cdfnode->tree = tree; } #endif break; case OC_Dimension: default: PANIC1("buildcdftree: unexpect OC node type: %d",(int)octype); } /* Avoid a rare but perhaps possible null-dereference of cdfnode. Not sure what error to throw, so using NC_EDAP: generic DAP error. */ if(!cdfnode) { return NC_EDAP; } #if 0 /* cross link */ assert(tree->root != NULL); cdfnode->root = tree->root; #endif if(ocrank > 0) defdimensions(ocnode,cdfnode,nccomm,tree); for(i=0;i<ocnsubnodes;i++) { OCddsnode ocsubnode; CDFnode* subnode; oc_dds_ithfield(nccomm->oc.conn,ocnode,i,&ocsubnode); ncerr = buildcdftreer(nccomm,ocsubnode,cdfnode,tree,&subnode); if(ncerr) { if(ocname) free(ocname); return ncerr; } nclistpush(cdfnode->subnodes,(void*)subnode); } nullfree(ocname); if(cdfnodep) *cdfnodep = cdfnode; return ncerr; }