source: branches/prototype-v0/zoo-project/zoo-kernel/meta_sql.c @ 845

Last change on this file since 845 was 845, checked in by djay, 7 years ago

Add the missing service_callback, service_json and meta_sql.

  • Property svn:keywords set to Id
File size: 19.0 KB
Line 
1/*
2 * Author : Gérald Fenoy
3 *
4 * Copyright 2017 GeoLabs SARL. All rights reserved.
5 *
6 * This work was supported by public funds received in the framework of GEOSUD,
7 * a project (ANR-10-EQPX-20) of the program "Investissements d'Avenir" managed
8 * by the French National Research Agency
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 */
28
29#ifdef META_DB
30#include "ogr_api.h"
31#include "ogrsf_frmts.h"
32#include "ogr_p.h"
33#if GDAL_VERSION_MAJOR >= 2
34#include <gdal_priv.h>
35#endif
36
37#include "meta_sql.h"
38#include "sqlapi.h"
39#include "response_print.h"
40#ifdef USE_HPC
41#include "service_internal_hpc.h"
42#endif
43#define META_SERVICES_LIST_ALL \
44  "select id,identifier,title,abstract,service_type,service_provider"\
45  " from ows_process"
46#define META_SERVICES_LIST_ALL_LENGTH 83
47
48#define META_SERVICES_KEYWORDS_FROM_PROCESS \
49  "SELECT keyword FROM CollectionDB.ows_Keywords where id in"\
50  " (SELECT keywords_id FROM CollectionDB.DescriptionsKeywordsAssignment"\
51  " where descriptions_id=%s) "
52#define META_SERVICES_KEYWORDS_FROM_PROCESS_LENGTH 162
53
54#define META_SERVICES_META_FROM_ANYTHING \
55  "SELECT title,role,href FROM CollectionDB.ows_Metadata where id in"\
56  " (SELECT metadata_id FROM CollectionDB.DescriptionsMetadataAssignment"\
57  " where descriptions_id=%s) "
58#define META_SERVICES_META_FROM_ANYTHING_LENGTH 162
59
60#define META_SERVICES_AP_FROM_ANYTHING \
61  "SELECT id,title,role,href FROM CollectionDB.ows_AdditionalParameters where id in"\
62  " (SELECT additional_parameters_id FROM CollectionDB.DescriptionsAdditionalParametersAssignment"\
63  " where descriptions_id=%s) "
64#define META_SERVICES_AP_FROM_ANYTHING_LENGTH 199
65
66#define META_SERVICES_AP_FROM_AP \
67  "SELECT key,value FROM CollectionDB.ows_AdditionalParameter where additional_parameters_id =$q$%s$q$"
68#define META_SERVICES_AP_FROM_AP_LENGTH 100
69
70#define META_SERVICES_LIST_INPUTS_FROM_PROCESS                          \
71  "select id, identifier,title,abstract,min_occurs,max_occurs from CollectionDB.ows_Input where id in (SELECT input_id from CollectionDB.ProcessInputAssignment where process_id=%s) order by id"
72#define META_SERVICES_LIST_INPUTS_FROM_PROCESS_LENGTH 190
73
74#define META_SERVICES_LIST_INPUTS_FROM_INPUT                            \
75  "select id, identifier,title,abstract,min_occurs,max_occurs from CollectionDB.ows_Input where id in (SELECT child_input from CollectionDB.InputInputAssignment where parent_input=%s) order by id"
76#define META_SERVICES_LIST_INPUTS_FROM_INPUT_LENGTH 193
77
78#define META_SERVICES_LIST_OUTPUTS_FROM_PROCESS \
79  "select id, identifier,title,abstract from CollectionDB.ows_Output where id in (SELECT output_id from CollectionDB.ProcessOutputAssignment where process_id=%s) order by id"
80#define META_SERVICES_LIST_OUTPUTS_FROM_PROCESS_LENGTH 171
81
82#define META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT \
83  "select id, identifier,title,abstract from CollectionDB.ows_Output where id in (SELECT child_output from CollectionDB.OutputOutputAssignment where parent_output=%s) order by id"
84#define META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT_LENGTH 176
85
86#define META_SERVICES_LIST_LITERAL_FROM_IO \
87  "select (SELECT name as type FROM CollectionDB.PrimitiveDatatypes where CollectionDB.PrimitiveDatatypes.id=data_type_id),default_value,(SELECT uom from CollectionDB.PrimitiveUOM where id=CollectionDB.LiteralDataDomain.uom),translate(translate(ARRAY((SELECT allowed_Value from CollectionDB.AllowedValues where id in (SELECT allowed_value_id from CollectionDB.AllowedValuesAssignment where literal_data_domain_id=CollectionDB.LiteralDataDomain.id)))::varchar,'{',''),'}',''),def as allowedvalues from CollectionDB.LiteralDataDomain where id in (SELECT data_description_id from CollectionDB.%sDataDescriptionAssignment where %s_id = %s);"
88#define META_SERVICES_LIST_LITERAL_FROM_IO_LENGTH 634
89
90#define META_SERVICES_LIST_FORMATS_FROM_IO \
91  "select mime_type,encoding,schema,maximum_megabytes,CASE WHEN use_mapserver THEN 'true' ELSE 'false' END, ms_styles, def from CollectionDB.ows_Format,CollectionDB.PrimitiveFormats where CollectionDB.ows_Format.primitive_format_id=CollectionDB.PrimitiveFormats.id and CollectionDB.ows_Format.id in (SELECT format_id from collectiondb.ows_datadescription where id in ( SELECT data_description_id from CollectionDB.%sDataDescriptionAssignment where %s_id = %s))"
92#define META_SERVICES_LIST_FORMATS_FROM_IO_LENGTH 458
93
94/**
95 * Create a new iotype pointer using field names from an OGRFeature
96 *
97 * @param f the OGRFeature
98 * @param fields the fields names
99 * @return the iotype
100 */
101iotype* getIoType(OGRFeature* f,const char** fields){
102  iotype* io=(iotype*)malloc(IOTYPE_SIZE);
103  io->content=NULL;
104  io->next=NULL;
105  for(int i=0;i<6;i++){
106    if(fields[i]==NULL)
107      return io;
108    const char* tmpS=f->GetFieldAsString( i );
109    if(strlen(tmpS)>0){
110      if(io->content==NULL)
111        io->content=createMap(fields[i],tmpS);
112      else
113        addToMap(io->content,fields[i],tmpS);
114    }
115  }
116  return io;
117}
118
119/**
120 * Fill the AdditionalParameters map with the data extracted from metadb
121 *
122 * @param conf the main configuration maps
123 * @param ap the map to fill
124 * @param dref the description identifier
125 * @return the number of metadata field found
126 */
127int fillAdditionalParameters(maps* conf,map** ap,const char* dref){
128  int res=0;
129  char* ioQuery=(char*)malloc((META_SERVICES_AP_FROM_ANYTHING_LENGTH+strlen(dref)+1)*sizeof(char));
130  sprintf(ioQuery,META_SERVICES_AP_FROM_ANYTHING,dref);
131  OGRFeature  *meta = NULL;
132  OGRLayer *metas=fetchSql(conf,0,ioQuery);
133  free(ioQuery);
134  int cnt=0;
135  char fields[3][255]={
136    "title",
137    "role",
138    "href"
139  };
140  while( (meta = metas->GetNextFeature()) != NULL ){
141    int i=0;
142    for(i=0;i<3;i++){     
143      const char *tmp=meta->GetFieldAsString(i+1);
144      if(strlen(tmp)>0)
145        if(*ap==NULL){
146          *ap=createMap(fields[i],tmp);
147          addToMap(*ap,"fromDb","true");
148        }
149        else
150          setMapArray(*ap,fields[i],res,tmp);
151    }
152    char* apQuery=(char*)malloc((META_SERVICES_AP_FROM_AP_LENGTH+strlen(dref)+1)*sizeof(char));
153    sprintf(apQuery,META_SERVICES_AP_FROM_AP,meta->GetFieldAsString(0));
154    OGRFeature  *adp = NULL;
155    OGRLayer *adps=fetchSql(conf,0,apQuery);
156    free(apQuery);
157    while( (adp = adps->GetNextFeature()) != NULL ){
158      addToMap(*ap,adp->GetFieldAsString(0),adp->GetFieldAsString(1));
159      OGRFeature::DestroyFeature( adp );
160    }
161    cleanFetchSql(conf,0,adps);
162    res++;
163    OGRFeature::DestroyFeature( meta );
164  }
165  cleanFetchSql(conf,0,metas);
166  return res;
167}
168
169/**
170 * Fill the metadata map with the data extracted from metadb
171 *
172 * @param conf the main configuration maps
173 * @param metadata the map to fill
174 * @param dref the description identifier
175 * @return the number of metadata field found
176 */
177int fillMetadata(maps* conf,map** metadata,const char* dref){
178  int res=0;
179  char* ioQuery=(char*)malloc((META_SERVICES_META_FROM_ANYTHING_LENGTH+strlen(dref)+1)*sizeof(char));
180  sprintf(ioQuery,META_SERVICES_META_FROM_ANYTHING,dref);
181  OGRFeature  *meta = NULL;
182  OGRLayer *metas=fetchSql(conf,0,ioQuery);
183  free(ioQuery);
184  int cnt=0;
185  char fields[3][255]={
186    "title",
187    "role",
188    "href"
189  };
190  while( (meta = metas->GetNextFeature()) != NULL ){
191    int i=0;
192    for(i=0;i<3;i++){
193      const char *tmp=meta->GetFieldAsString(i);
194      if(strlen(tmp)>0)
195        if(*metadata==NULL)
196          *metadata=createMap(fields[i],tmp);
197        else
198          addToMap(*metadata,fields[i],tmp);
199    }
200    res++;
201    OGRFeature::DestroyFeature( meta );
202  }
203  cleanFetchSql(conf,0,metas);
204  return res;
205}
206
207/**
208 * Try to fill the default/supported map for the LiteralData with the data
209 * extracted from metadb.
210 *
211 * @param conf the main configuration maps
212 * @param in the element to fill default/supported
213 * @param input the OGRFeature corresponding to the input/output
214 * @param ltype the element type ("Input" or "Output")
215 * @return the number of default/supported definition found
216 */
217int fillLiteralData(maps* conf,elements* in,OGRFeature  *input,const char* ltype){
218  int res=0;
219  char* ioQuery=(char*)malloc((META_SERVICES_LIST_LITERAL_FROM_IO_LENGTH+(strlen(ltype)*2)+strlen(input->GetFieldAsString( 0 ))+1)*sizeof(char));
220  sprintf(ioQuery,META_SERVICES_LIST_LITERAL_FROM_IO,ltype,ltype,input->GetFieldAsString( 0 ));
221  OGRFeature  *io = NULL;
222  OGRLayer *ios=fetchSql(conf,0,ioQuery);
223  free(ioQuery);
224  int ioCnt=0;
225  const char* fields[5]={"dataType","value","uom","AllowedValues",NULL};
226  while( (io = ios->GetNextFeature()) != NULL ){
227    iotype* currentIoType;
228    if(strncmp(io->GetFieldAsString( 4 ),"1",1)==0){
229      in->defaults=getIoType(io,fields);
230    }else{
231      if(in->supported==NULL)
232        in->supported=getIoType(io,fields);
233      else{
234        iotype* p=in->supported;
235        while(p->next!=NULL){
236          p=p->next;
237        }
238        p->next=getIoType(io,fields);
239      }
240    }
241    in->format=strdup("LiteralData");
242    res++;
243    OGRFeature::DestroyFeature( io );
244  }
245  cleanFetchSql(conf,0,ios);
246  return res;
247}
248
249/**
250 * Try to fill the default/supported map for the ComplexData with the data
251 * extracted from metadb.
252 *
253 * @param conf the main configuration maps
254 * @param in the element to fill default/supported
255 * @param input the OGRFeature corresponding to the input/output
256 * @param ltype the element type ("Input" or "Output")
257 * @return the number of default/supported definition found
258 */
259int fillComplexData(maps* conf,elements* in,OGRFeature  *input,const char* ltype){
260  int res=0;
261  char* ioQuery=(char*)malloc((META_SERVICES_LIST_FORMATS_FROM_IO_LENGTH+(strlen(ltype)*2)+strlen(input->GetFieldAsString( 0 ))+1)*sizeof(char));
262  sprintf(ioQuery,META_SERVICES_LIST_FORMATS_FROM_IO,ltype,ltype,input->GetFieldAsString( 0 ));
263  OGRFeature  *io = NULL;
264  OGRLayer *ios=fetchSql(conf,0,ioQuery);
265  free(ioQuery);
266  int ioCnt=0;
267  const char* fields[6]={"mimeType","ecoding","schema","maximumMegabytes","useMapserver","msStyle"};
268  while( (io = ios->GetNextFeature()) != NULL ){
269    iotype* currentIoType;
270    if(strncmp(io->GetFieldAsString( 6 ),"1",1)==0){
271      in->defaults=getIoType(io,fields);
272    }else{
273      if(in->supported==NULL)
274        in->supported=getIoType(io,fields);
275      else{
276        iotype* p=in->supported;
277        while(p->next!=NULL){
278          p=p->next;
279        }
280        p->next=getIoType(io,fields);
281      }
282    }
283    in->format=strdup("ComplexData");
284    res++;
285    OGRFeature::DestroyFeature( io );
286  }
287  cleanFetchSql(conf,0,ios);
288  return res;
289}
290
291/**
292 * Extract input definition from metadb
293 *
294 * @param conf the main configuration maps
295 * @param input the OGRFeature pointing to an input
296 * @return a new elements* corresponding to the current input
297 */
298elements* extractInput(maps* conf,OGRFeature *input){
299  fprintf(stderr,"************************* %s %s %d\n\n",input->GetFieldAsString( 0 ),__FILE__,__LINE__);
300  fprintf(stderr,"************************* %s %s %d\n\n",input->GetFieldAsString( 1 ),__FILE__,__LINE__);
301  elements* res=createElements(input->GetFieldAsString( 1 ));
302  res->content=createMap("title",input->GetFieldAsString( 2 ));
303  addToMap(res->content,"abstract",input->GetFieldAsString( 3 ));
304  addToMap(res->content,"minOccurs",input->GetFieldAsString( 4 ));
305  addToMap(res->content,"maxOccurs",input->GetFieldAsString( 5 ));
306  // Extract metadata
307  fillMetadata(conf,&res->metadata,input->GetFieldAsString( 0 ));
308  fillAdditionalParameters(conf,&res->additional_parameters,input->GetFieldAsString( 0 ));
309  res->defaults=NULL;
310  res->supported=NULL;
311  res->child=NULL;
312  res->next=NULL;
313  // Extract iotypes
314  int ioCnt=fillLiteralData(conf,res,input,"Input");
315  if(ioCnt==0){
316    ioCnt=fillComplexData(conf,res,input,"Input");
317  }
318  if(ioCnt==0){
319    char* nestedInputsQuery=(char*)malloc((META_SERVICES_LIST_INPUTS_FROM_INPUT_LENGTH+strlen(input->GetFieldAsString( 0 ))+1)*sizeof(char));
320    sprintf(nestedInputsQuery,META_SERVICES_LIST_INPUTS_FROM_INPUT,input->GetFieldAsString( 0 ));
321    OGRFeature  *ninput = NULL;
322    OGRLayer *ninputs=fetchSql(conf,0,nestedInputsQuery);
323    free(nestedInputsQuery);
324    while( (ninput = ninputs->GetNextFeature()) != NULL ){
325      elements* nin=extractInput(conf,ninput);
326      addToElements(&res->child,nin);
327      freeElements(&nin);
328      free(nin);
329      OGRFeature::DestroyFeature( ninput );
330    }
331    cleanFetchSql(conf,0,ninputs);
332  }
333  return res;
334}
335
336/**
337 * Extract output definition from metadb
338 *
339 * @param conf the main configuration maps
340 * @param output the OGRFeature pointing to an output
341 * @return a new elements* corresponding to the current output
342 */
343elements* extractOutput(maps* conf,OGRFeature *output){
344  elements* res=createElements(output->GetFieldAsString( 1 ));
345  res->content=createMap("title",output->GetFieldAsString( 2 ));
346  addToMap(res->content,"abstract",output->GetFieldAsString( 3 ));
347  fillMetadata(conf,&res->metadata,output->GetFieldAsString( 0 ));
348  fillAdditionalParameters(conf,&res->additional_parameters,output->GetFieldAsString( 0 ));
349  res->defaults=NULL;
350  res->supported=NULL;
351  res->child=NULL;
352  res->next=NULL;
353  int ioCnt=fillLiteralData(conf,res,output,"Output");
354  if(ioCnt==0)
355    ioCnt=fillComplexData(conf,res,output,"Output");
356  char* nestedOutputsQuery=(char*)malloc((META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT_LENGTH+strlen(output->GetFieldAsString( 0 ))+1)*sizeof(char));
357  sprintf(nestedOutputsQuery,META_SERVICES_LIST_OUTPUTS_FROM_OUTPUT,output->GetFieldAsString( 0 ));
358  OGRFeature  *noutput = NULL;
359  OGRLayer *noutputs=fetchSql(conf,0,nestedOutputsQuery);
360  free(nestedOutputsQuery);
361  while( (noutput = noutputs->GetNextFeature()) != NULL ){
362    elements* nout=extractInput(conf,noutput);
363    addToElements(&res->child,nout);
364    freeElements(&nout);
365    free(nout);
366    OGRFeature::DestroyFeature( noutput );
367  }
368  cleanFetchSql(conf,0,noutputs);
369  return res;
370}
371
372/**
373 * Extract service from metadb
374 *
375 * @param conf the main configuration maps
376 * @param serviceName the service name
377 * @param minimal 1 for minimal metadata extraction (GetCapabilities), 0 in other cases.
378 * @return a new service* corresponding to the service
379 */
380service* extractServiceFromDb(maps* conf,const char* serviceName,int minimal){
381  OGRFeature  *poFeature = NULL;
382  char* tmpQuery=(char*)malloc((META_SERVICES_LIST_ALL_LENGTH+strlen(serviceName)+21)*sizeof(char));
383  sprintf(tmpQuery,"%s WHERE identifier='%s'",META_SERVICES_LIST_ALL,serviceName); 
384  OGRLayer *res=fetchSql(conf,0,tmpQuery);
385  free(tmpQuery);
386  if(res!=NULL){
387    while( (poFeature = res->GetNextFeature()) != NULL ){
388      service* s = (service*) malloc(SERVICE_SIZE);
389      s->name = strdup(poFeature->GetFieldAsString( 1 ));
390      s->content = createMap("title",poFeature->GetFieldAsString( 2 ));
391      addToMap(s->content,"abstract",poFeature->GetFieldAsString( 3 ));
392      addToMap(s->content,"serviceType",poFeature->GetFieldAsString( 4 ));
393      addToMap(s->content,"serviceProvider",poFeature->GetFieldAsString( 5 ));
394      addToMap(s->content,"fromDb","true");
395      s->metadata=NULL;
396      fillMetadata(conf,&s->metadata,poFeature->GetFieldAsString( 0 ));
397      s->additional_parameters=NULL;
398      fillAdditionalParameters(conf,&s->additional_parameters,poFeature->GetFieldAsString( 0 ));
399      s->inputs=NULL;
400      s->outputs=NULL;
401      if(minimal==1){
402        OGRFeature::DestroyFeature( poFeature );
403        return s;
404      }
405      char* inputsQuery=(char*)malloc((META_SERVICES_LIST_INPUTS_FROM_PROCESS_LENGTH+strlen(poFeature->GetFieldAsString( 0 ))+1)*sizeof(char));
406      sprintf(inputsQuery,META_SERVICES_LIST_INPUTS_FROM_PROCESS,poFeature->GetFieldAsString( 0 ));
407      OGRFeature  *input = NULL;
408      OGRLayer *inputs=fetchSql(conf,0,inputsQuery);
409      free(inputsQuery);
410      while( (input = inputs->GetNextFeature()) != NULL ){
411        elements* in=extractInput(conf,input);
412        addToElements(&s->inputs,in);
413        freeElements(&in);
414        free(in);       
415        OGRFeature::DestroyFeature( input );
416      }
417      cleanFetchSql(conf,0,inputs);
418      char* outputsQuery=(char*)malloc((META_SERVICES_LIST_OUTPUTS_FROM_PROCESS_LENGTH+strlen(poFeature->GetFieldAsString( 0 ))+1)*sizeof(char));
419      sprintf(outputsQuery,META_SERVICES_LIST_OUTPUTS_FROM_PROCESS,poFeature->GetFieldAsString( 0 ));
420      OGRFeature  *output = NULL;
421      OGRLayer *outputs=fetchSql(conf,0,outputsQuery);
422      free(outputsQuery);
423      s->outputs=NULL;
424      while( (output = outputs->GetNextFeature()) != NULL ){
425        elements* in=extractOutput(conf,output);
426        addToElements(&s->outputs,in);
427        freeElements(&in);
428        free(in);
429        OGRFeature::DestroyFeature( output );
430      }
431      cleanFetchSql(conf,0,outputs);
432      OGRFeature::DestroyFeature( poFeature );
433      cleanFetchSql(conf,0,res);
434      return s;
435    }
436  }
437  cleanFetchSql(conf,0,res);
438  return NULL;
439}
440
441/**
442 * Extract every service definitions from metadb
443 *
444 * @param reg the registry
445 * @param conf the main configuration maps
446 * @param n the node where to add the services found
447 * @param func the C function to call for each service found
448 * @param minimal 1 for minimal metadata extraction (GetCapabilities), 0 in other cases.
449 * @return the number of services found, -1 in case of failure
450 */
451int fetchServicesFromDb(registry* reg,maps* conf, xmlDocPtr doc, xmlNodePtr n,
452                        void (func) (registry *, maps *, xmlDocPtr, xmlNodePtr,
453                                     service *), int minimal ){
454  int result=0;
455  _init_sql(conf,"metadb");
456  if(getMapFromMaps(conf,"lenv","dbIssue")!=NULL)
457    return -1;
458  // Fetch every services
459  OGRLayer *res=fetchSql(conf,0,META_SERVICES_LIST_ALL);
460  if(res!=NULL){
461    OGRFeature  *poFeature = NULL;
462    const char *tmp1;
463    poFeature = res->GetNextFeature();
464    while( poFeature != NULL ){
465      fprintf(stderr,"************************* %s %d\n\n",__FILE__,__LINE__);
466      fflush(stderr);
467      service* s=extractServiceFromDb(conf,poFeature->GetFieldAsString( 1 ),minimal);
468#ifdef USE_HPC
469      addNestedOutputs(&s);
470#endif
471      fprintf(stderr,"************************* %s %d\n\n",__FILE__,__LINE__);
472      fflush(stderr);
473      dumpMap(s->content);
474      fprintf(stderr,"************************* %s %d\n\n",__FILE__,__LINE__);
475      fflush(stderr);
476      func(reg,conf,doc,n,s);
477      fprintf(stderr,"************************* %s %d\n\n",__FILE__,__LINE__);
478      fflush(stderr);
479      freeService(&s);
480      fprintf(stderr,"************************* %s %d\n\n",__FILE__,__LINE__);
481      fflush(stderr);
482      free(s);
483      OGRFeature::DestroyFeature( poFeature );
484      poFeature = res->GetNextFeature();
485      result++;
486      fprintf(stderr,"************************* %s %d\n\n",__FILE__,__LINE__);
487      fflush(stderr);
488    }
489  }
490  fprintf(stderr,"************************* %s %d\n\n",__FILE__,__LINE__);
491  fflush(stderr);
492  return result;
493}
494
495#endif
Note: See TracBrowser for help on using the repository browser.

Search

Context Navigation

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png