/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. *********************************************************************/ #include "ncdap.h" #define OCCHECK(exp) if((ocstat = (exp))) {THROWCHK(ocstat); goto done;} /* Forward */ static NCerror buildattribute(char*,nc_type,size_t,char**,NCattribute**); /* Invoke oc_merge_das and then extract special attributes such as "strlen" and "dimname" and stuff from DODS_EXTRA. */ int dapmerge(NCDAPCOMMON* nccomm, CDFnode* ddsroot, OCddsnode dasroot) { int i,j; NCerror ncstat = NC_NOERR; OCerror ocstat = OC_NOERR; NClist* allnodes; OClink conn; char* ocname = NULL; char** values = NULL; conn = nccomm->oc.conn; if(ddsroot == NULL || dasroot == NULL) return NC_NOERR; /* Merge the das tree onto the dds tree */ ocstat = oc_merge_das(nccomm->oc.conn,dasroot,ddsroot->ocnode); if(ocstat != OC_NOERR) goto done; /* Create attributes on CDFnodes */ allnodes = ddsroot->tree->nodes; for(i=0;iocnode; size_t attrcount; OCtype ocetype; OCCHECK(oc_dds_attr_count(conn,ocnode,&attrcount)); for(j=0;j 0) { values = (char**)malloc(sizeof(char*)*nvalues); if(values == NULL) {ncstat = NC_ENOMEM; goto done;} OCCHECK(oc_dds_attr(conn,ocnode,j,NULL,NULL,NULL,values)); } ncstat = buildattribute(ocname,octypetonc(ocetype),nvalues,values,&att); if(ncstat != NC_NOERR) goto done; if(node->attributes == NULL) node->attributes = nclistnew(); nclistpush(node->attributes,(void*)att); if(strncmp(ocname,"DODS",strlen("DODS"))==0) { att->invisible = 1; /* Define extra semantics associated with DODS and DODS_EXTRA attributes */ if(strcmp(ocname,"DODS.strlen")==0 || strcmp(ocname,"DODS_EXTRA.strlen")==0) { unsigned int maxstrlen = 0; if(values != NULL) { if(0==sscanf(values[0],"%u",&maxstrlen)) maxstrlen = 0; } node->dodsspecial.maxstrlen = maxstrlen; #ifdef DEBUG fprintf(stderr,"%s.maxstrlen=%d\n",node->ocname,(int)node->dodsspecial.maxstrlen); #endif } else if(strcmp(ocname,"DODS.dimName")==0 || strcmp(ocname,"DODS_EXTRA.dimName")==0) { if(values != NULL) { node->dodsspecial.dimname = nulldup(values[0]); #ifdef DEBUG fprintf(stderr,"%s.dimname=%s\n",node->ocname,node->dodsspecial.dimname); #endif } else node->dodsspecial.dimname = NULL; } else if(strcmp(ocname,"DODS.Unlimited_Dimension")==0 || strcmp(ocname,"DODS_EXTRA.Unlimited_Dimension")==0) { if(values != NULL) { if(nccomm->cdf.recorddimname != NULL) nclog(NCLOGWARN,"Duplicate DODS_EXTRA:Unlimited_Dimension specifications"); else nccomm->cdf.recorddimname = nulldup(values[0]); #ifdef DEBUG fprintf(stderr,"%s.Unlimited_Dimension=%s\n",node->ocname,nccomm->cdf.recorddimname); #endif } } } /* clean up */ if(values) { oc_reclaim_strings(nvalues,values); free(values); values = NULL; } } } done: if(values != NULL) free(values); if(ocname != NULL) free(ocname); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); } /* Build an NCattribute */ static NCerror buildattribute(char* name, nc_type ptype, size_t nvalues, char** values, NCattribute** attp) { int i; NCerror ncstat = NC_NOERR; NCattribute* att = NULL; att = (NCattribute*)calloc(1,sizeof(NCattribute)); MEMCHECK(att,NC_ENOMEM); att->name = nulldup(name); att->etype = ptype; att->values = nclistnew(); for(i=0;ivalues,(void*)nulldup(values[i])); if(attp) *attp = att; else free(att); return THROW(ncstat); } #if 0 /* Given a das attribute walk it to see if it has at least 1 actual attribute (no recursion) */ static int hasattribute(OClink conn, OCdasnode dasnode) { int i; OCerror ocstat = OC_NOERR; int tf = 0; /* assume false */ OCtype ocsubtype; NClist* subnodes = nclistnew(); OCCHECK(oc_dds_octype(conn,dasnode,&ocsubtype)); if(ocsubtype == OC_Attribute) return 1; /* this is an attribute */ ASSERT((ocsubtype == OC_Attributeset)); OCCHECK(collect_subnodes(conn,dasnode,subnodes)); for(i=0;ioc.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;ifullname :: 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;iocname)==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;iattributes == NULL) dds->attributes = nclistnew(); /* assign the simple attributes in the das set to this dds node*/ OCCHECK(oc_inq_nsubnodes(conn,das,&nsubnodes)); OCCHECK(oc_inq_subnodes(conn,das,&subnodes)); for(i=0;iattributes,(void*)att); } else if(octype == OC_Attributeset && (strcmp(ocname,"DODS")==0 || strcmp(ocname,"DODS_EXTRA")==0)) { /* Turn the DODS special attributes into into special attributes for dds node */ OCCHECK(oc_inq_nsubnodes(conn,attnode,&ndodsnodes)); OCCHECK(oc_inq_subnodes(conn,attnode,&dodsnodes)); for(j=0;jinvisible = 1; nclistpush(dds->attributes,(void*)att); /* Define extra semantics associated with DODS and DODS_EXTRA attribute */ if(strcmp(dodsname,"strlen")==0) { unsigned int maxstrlen = 0; if(nclistlength(stringvalues) > 0) { char* stringval = (char*)nclistget(stringvalues,0); if(0==sscanf(stringval,"%u",&maxstrlen)) maxstrlen = 0; } dds->dodsspecial.maxstrlen = maxstrlen; #ifdef DEBUG fprintf(stderr,"%s.maxstrlen=%d\n",dds->ocname,(int)dds->dodsspecial.maxstrlen); #endif } else if(strcmp(dodsname,"dimName")==0) { if(nclistlength(stringvalues) > 0) { char* stringval = (char*)nclistget(stringvalues,0); dds->dodsspecial.dimname = nulldup(stringval); #ifdef DEBUG fprintf(stderr,"%s.dimname=%s\n",dds->ocname,dds->dodsspecial.dimname); #endif } else dds->dodsspecial.dimname = NULL; } else if(strcmp(dodsname,"Unlimited_Dimension")==0) { if(nccomm->cdf.recorddimname != NULL) { nclog(NCLOGWARN,"Duplicate DODS_EXTRA:Unlimited_Dimension specifications"); } else if(nclistlength(stringvalues) > 0) { char* stringval = (char*)nclistget(stringvalues,0); nccomm->cdf.recorddimname = nulldup(stringval); #ifdef DEBUG fprintf(stderr,"%s.Unlimited_Dimension=%s\n",dds->ocname,nccomm->cdf.recorddimname); #endif } } /* else ignore */ nullfree(dodsname); } nullfree(dodsnodes); } nullfree(ocname); } done: nullfree(subnodes); if(ocstat != OC_NOERR) ncstat = ocerrtoncerr(ocstat); return THROW(ncstat); } static int isglobalname(char* name) { int len = strlen(name); int glen = strlen("global"); char* p; if(len < glen) return 0; p = name + (len - glen); if(strcasecmp(p,"global") != 0) return 0; return 1; } static OCerror collect_alldasnodes(OClink link, OCddsnode dasnode, NClist* alldasnodes) { size_t nsubnodes,i; OCerror ocstat = OC_NOERR; nclistpush(alldasnodes,(void*)dasnode); ocstat = oc_dds_nsubnodes(link,dasnode,&nsubnodes); if(ocstat != OC_NOERR) goto done; for(i=0;i