//--------------------------------------------------------------------------- int enviar_infoReduce_job(int socket_job,t_reduce_dest* reduce_dest, t_reduce_nodo_dest* nodo_host) { int result = 1; t_buffer* reduce_to_Nodo_buff; reduce_to_Nodo_buff = buffer_create_with_protocol(EXECUTE_REDUCE); buffer_add_int(reduce_to_Nodo_buff, nodo_host->id_nodo); buffer_add_string(reduce_to_Nodo_buff, reduce_dest->temp_file_name); buffer_add_int(reduce_to_Nodo_buff, list_size(nodo_host->path_temps)); void _buffer_add_path(char* path) { buffer_add_string(reduce_to_Nodo_buff, path); }
/* * Return the column's name matching the specified number from table * (Only use in specific FE position function, so not directly inside * storage handle mechanism) */ buffer *ows_psql_column_name(ows * o, buffer * layer_name, int number) { buffer *sql; PGresult *res; buffer *column; assert(o); assert(layer_name); sql = buffer_init(); column = buffer_init(); buffer_add_str(sql, "SELECT a.attname FROM pg_class c, pg_attribute a, pg_type t WHERE c.relname ='"); buffer_copy(sql, layer_name); buffer_add_str(sql, "' AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid AND a.attnum = "); buffer_add_int(sql, number); res = ows_psql_exec(o, sql->buf); buffer_free(sql); if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) { PQclear(res); return column; } buffer_add_str(column, PQgetvalue(res, 0, 0)); PQclear(res); return column; }
/* * Retrieve a srs from a srid */ buffer *ows_srs_get_from_a_srid(ows * o, int srid) { buffer *b; buffer *sql; PGresult *res; assert(o); sql = buffer_init(); buffer_add_str(sql, "SELECT auth_name||':'||auth_srid AS srs "); buffer_add_str(sql, "FROM spatial_ref_sys "); buffer_add_str(sql, "WHERE srid="); buffer_add_int(sql, srid); res = ows_psql_exec(o, sql->buf); buffer_free(sql); b = buffer_init(); if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) { PQclear(res); return b; } buffer_add_str(b, PQgetvalue(res, 0, 0)); PQclear(res); return b; }
/* * Set projection value into srs structure */ bool ows_srs_set_from_srid(ows * o, ows_srs * s, int srid) { PGresult *res; buffer *sql; assert(o); assert(s); if (srid == -1 || srid == 0) { s->srid = -1; buffer_empty(s->auth_name); s->auth_srid = 0; s->is_degree = true; s->is_reverse_axis = false; s->is_eastern_axis = false; return true; } sql = buffer_init(); buffer_add_str(sql, "SELECT auth_name, auth_srid, "); buffer_add_str(sql, "position('+units=m ' in proj4text), "); buffer_add_str(sql, "(position('AXIS[\"X\",NORTH]]' in srtext) + position('AXIS[\"Northing\",NORTH]]' in srtext)) "); buffer_add_str(sql, "FROM spatial_ref_sys WHERE srid = '"); buffer_add_int(sql, srid); buffer_add_str(sql, "'"); res = ows_psql_exec(o, sql->buf); buffer_free(sql); /* If query dont return exactly 1 result, it mean projection not handled */ if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) { PQclear(res); return false; } buffer_add_str(s->auth_name, PQgetvalue(res, 0, 0)); s->auth_srid = atoi(PQgetvalue(res, 0, 1)); s->srid = srid; /* Such a way to know if units is meter or degree */ if (atoi(PQgetvalue(res, 0, 2)) == 0) s->is_degree = true; else s->is_degree = false; /* Is easting-northing SRID ? */ if (atoi(PQgetvalue(res, 0, 3)) != 0) s->is_eastern_axis = true; PQclear(res); return true; }
//--------------------------------------------------------------------------- int enviar_infoMap_job(int socket_job,t_map_dest* map_dest){ int result = 1; t_buffer* map_to_Nodo_buff; map_to_Nodo_buff = buffer_create_with_protocol(EXECUTE_MAP); buffer_add_int(map_to_Nodo_buff, map_dest->id_nodo); buffer_add_int(map_to_Nodo_buff, map_dest->block); buffer_add_string(map_to_Nodo_buff, map_dest->temp_file_name); result = send_buffer_and_destroy(socket_job, map_to_Nodo_buff); result = (result > 0) ? send_entire_file_by_parts(socket_job, conf->path_map, MAX_PART_SIZE) : result; if(result<= 0) { log_error(paranoid_log, "No se pudo enviar Instrucciones de Map"); } else { log_info(paranoid_log, "Se envio correctamente Instrucciones de Map"); } return result; }
/* * Convert a bbox to PostGIS query Polygon */ void ows_bbox_to_query(ows *o, ows_bbox *bbox, buffer *query) { double x1, y1, x2, y2; assert(o); assert(bbox); assert(query); if (bbox->srs->is_reverse_axis) { x1 = bbox->ymin; y1 = bbox->xmin; x2 = bbox->ymax; y2 = bbox->xmax; } else { x1 = bbox->xmin; y1 = bbox->ymin; x2 = bbox->xmax; y2 = bbox->ymax; } /* We use explicit POLYGON geometry rather than BBOX related to precision handle (Float4 vs Double) */ buffer_add_str(query, "'SRID="); buffer_add_int(query, bbox->srs->srid); buffer_add_str(query, ";POLYGON(("); buffer_add_double(query, x1); buffer_add_str(query, " "); buffer_add_double(query, y1); buffer_add_str(query, ","); buffer_add_double(query, x1); buffer_add_str(query, " "); buffer_add_double(query, y2); buffer_add_str(query, ","); buffer_add_double(query, x2); buffer_add_str(query, " "); buffer_add_double(query, y2); buffer_add_str(query, ","); buffer_add_double(query, x2); buffer_add_str(query, " "); buffer_add_double(query, y1); buffer_add_str(query, ","); buffer_add_double(query, x1); buffer_add_str(query, " "); buffer_add_double(query, y1); buffer_add_str(query, "))'::geometry"); /* FIXME what about geography ? */ }
/* * Set projection value into srs structure */ bool ows_srs_set(ows * o, ows_srs * c, const buffer * auth_name, int auth_srid) { PGresult *res; buffer *sql; assert(o); assert(c); assert(o->pg); assert(auth_name); sql = buffer_init(); buffer_add_str(sql, "SELECT srid, position('+units=m ' in proj4text)"); buffer_add_str(sql, ", (position('AXIS[\"X\",NORTH]]' in srtext) + position('AXIS[\"Northing\",NORTH]]' in srtext))"); buffer_add_str(sql, " FROM spatial_ref_sys WHERE auth_name='"); buffer_copy(sql, auth_name); buffer_add_str(sql, "' AND auth_srid="); buffer_add_int(sql, auth_srid); res = ows_psql_exec(o, sql->buf); buffer_free(sql); /* If query dont return exactly 1 result, it means projection is not handled */ if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) { PQclear(res); return false; } buffer_empty(c->auth_name); buffer_copy(c->auth_name, auth_name); c->auth_srid = auth_srid; c->srid = atoi(PQgetvalue(res, 0, 0)); /* Such a way to know if units is meter or degree */ if (atoi(PQgetvalue(res, 0, 1)) == 0) c->is_degree = true; else c->is_degree = false; /* Is easting-northing SRID ? */ if (atoi(PQgetvalue(res, 0, 2)) != 0) c->is_eastern_axis = true; PQclear(res); return true; }
//--------------------------------------------------------------------------- void hilo_map_job(t_map_dest* map_dest) { t_buffer* result_map_buff; char *ip_nodo = from_int_to_inet_addr(map_dest->ip_nodo); int result; log_info(paranoid_log, "Realizando Operación de Map ID:%i, en Nodo: %i, IP: %s, Port: %i, Block: %i Temp: %s", map_dest->id, map_dest->id_nodo, ip_nodo, map_dest->puerto_nodo, map_dest->block, map_dest->temp_file_name); int socket_nodo = solicitarConexionConNodo(ip_nodo, map_dest->puerto_nodo, map_dest->id_nodo); result = (socket_nodo != -1) ? enviar_infoMap_job(socket_nodo, map_dest) : -1; uint32_t answer_map = 0; result = (result > 0) ? receive_answer_map(socket_nodo, &answer_map) : result; if(socket_nodo != -1) { if(result > 0) { if(answer_map == INCORRECT_NODO) { result_map_buff = buffer_create_with_protocol(NODO_NOT_FOUND); } else { result_map_buff = buffer_create_with_protocol(answer_map); } close(socket_nodo); } else { result_map_buff = buffer_create_with_protocol(ERROR_IN_CONNECTION); } } else { result_map_buff = buffer_create_with_protocol(NODO_NOT_FOUND); } buffer_add_int(result_map_buff,map_dest->id); pthread_mutex_lock(&conex_marta_ready); result = send_buffer_and_destroy(socket_marta,result_map_buff); pthread_mutex_unlock(&conex_marta_ready); if(result <= 0) { log_error(paranoid_log,"No se pudo enviar respuesta de Map a MaRTA"); } free(ip_nodo); free_map_dest(map_dest); }
/* * Transform a GML geometry to PostGIS EWKT * Return NULL on error */ buffer * ows_psql_gml_to_sql(ows * o, xmlNodePtr n, int srid) { PGresult *res; xmlNodePtr g; buffer *result, *sql, *gml; assert(o); assert(n); g = ows_psql_recursive_parse_gml(o, n, NULL); if (!g) return NULL; /* No Geometry founded in GML doc */ /* Retrieve the sub doc and launch GML parse via PostGIS */ gml = buffer_init(); cgi_add_xml_into_buffer(gml, g); sql = buffer_init(); buffer_add_str(sql, "SELECT ST_GeomFromGML('"); buffer_add_str(sql, gml->buf); if (ows_version_get(o->postgis_version) >= 200) { buffer_add_str(sql, "',"); buffer_add_int(sql, srid); buffer_add_str(sql, ")"); } else { /* Means PostGIS 1.5 */ buffer_add_str(sql, "')"); } res = ows_psql_exec(o, sql->buf); buffer_free(gml); /* GML Parse errors cases */ if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) { buffer_free(sql); PQclear(res); return NULL; } result = buffer_init(); buffer_add_str(result, PQgetvalue(res, 0, 0)); PQclear(res); /* Check if geometry is valid */ if (o->check_valid_geom) { buffer_empty(sql); buffer_add_str(sql, "SELECT ST_IsValid('"); buffer_add_str(sql, result->buf); buffer_add_str(sql, "')"); res = ows_psql_exec(o, sql->buf); if ( PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1 || (char) PQgetvalue(res, 0, 0)[0] != 't') { buffer_free(sql); buffer_free(result); PQclear(res); return NULL; } PQclear(res); } buffer_free(sql); return result; }
/* * Generate a new buffer id supposed to be unique for a given layer name */ buffer *ows_psql_generate_id(ows * o, buffer * layer_name) { ows_layer_node *ln; buffer * id, *sql_id; FILE *fp; PGresult * res; int i, seed_len; char * seed = NULL; assert(o); assert(o->layers); assert(layer_name); /* Retrieve layer node pointer */ for (ln = o->layers->first ; ln ; ln = ln->next) { if (ln->layer->name && ln->layer->storage && !strcmp(ln->layer->name->buf, layer_name->buf)) break; } assert(ln); id = buffer_init(); /* If PK have a sequence in PostgreSQL database, * retrieve next available sequence value */ if (ln->layer->storage->pkey_sequence) { sql_id = buffer_init(); buffer_add_str(sql_id, "SELECT nextval('"); buffer_copy(sql_id, ln->layer->storage->pkey_sequence); buffer_add_str(sql_id, "');"); res = ows_psql_exec(o, sql_id->buf); buffer_free(sql_id); if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) { buffer_add_str(id, (char *) PQgetvalue(res, 0, 0)); PQclear(res); return id; } /* FIXME: Shouldn't we return an error there instead ? */ PQclear(res); } /* * If we don't have a PostgreSQL Sequence, we will try to * generate a pseudo random keystring using /dev/urandom * Will so work only on somes/commons Unix system */ seed_len = 6; seed = malloc(sizeof(char) * (seed_len * 3 + 1)); /* multiply by 3 to be able to deal with hex2dec conversion */ assert(seed); seed[0] = '\0'; fp = fopen("/dev/urandom","r"); if (fp) { for (i=0 ; i<seed_len ; i++) sprintf(seed,"%s%03d", seed, fgetc(fp)); fclose(fp); buffer_add_str(id, seed); free(seed); return id; } free(seed); /* Case where we not using PostgreSQL sequence, * and OS don't have a /dev/urandom support * This case don't prevent to produce ID collision * Don't use it unless really no others choices !!! */ srand((int) (time(NULL) ^ rand() % 1000) + 42); srand((rand() % 1000 ^ rand() % 1000) + 42); buffer_add_int(id, rand()); return id; }
//--------------------------------------------------------------------------- void hilo_reduce_job(t_reduce_dest* reduce_dest) { int result = 1; uint32_t answer_reduce = 0; mostrar_reduce_dest(reduce_dest); int _isNodoHost(t_reduce_nodo_dest* nodo) { return reduce_dest->id_nodo_host == nodo->id_nodo; } t_reduce_nodo_dest* nodo_host = list_remove_by_condition(reduce_dest->list_nodos, (void *)_isNodoHost); char *ip_nodo = from_int_to_inet_addr(nodo_host->ip_nodo); int socket_nodo = solicitarConexionConNodo(ip_nodo, nodo_host->puerto_nodo, nodo_host->id_nodo); if(socket_nodo != 1) { result = enviar_infoReduce_job(socket_nodo, reduce_dest, nodo_host); result = (result > 0) ? receive_answer_reduce(socket_nodo, &answer_reduce) : result; } else { answer_reduce = INCORRECT_NODO; } if(result <= 0) { answer_reduce = REDUCE_NOT_OK; } t_buffer* reduce_result_buff; switch(answer_reduce) { case REDUCE_OK: case REDUCE_NOT_OK: reduce_result_buff = buffer_create_with_protocol(answer_reduce); if(reduce_dest->prot == ORDER_PARTIAL_REDUCE) { buffer_add_int(reduce_result_buff, reduce_dest->id_nodo_host); } break; case INCORRECT_NODO: reduce_result_buff = buffer_create_with_protocol(NODO_NOT_FOUND); if(reduce_dest->prot == ORDER_REDUCE) { buffer_add_int(reduce_result_buff, 1); buffer_add_int(reduce_result_buff, nodo_host->id_nodo); } break; case NODO_NOT_FOUND: reduce_result_buff = buffer_create_with_protocol(NODO_NOT_FOUND); if(reduce_dest->prot == ORDER_REDUCE) { uint32_t i,amount_nodes = 0; result = receive_int_in_order(socket_nodo, &amount_nodes); buffer_add_int(reduce_result_buff, amount_nodes); for(i=0;(i<amount_nodes) && (result > 0); i++) { uint32_t id_nodo = 0; result = receive_int_in_order(socket_nodo, &id_nodo); buffer_add_int(reduce_result_buff, id_nodo); } if(result <= 0) { buffer_destroy(reduce_result_buff); reduce_result_buff = buffer_create_with_protocol(REDUCE_NOT_OK); } } break; case TEMP_NOT_FOUND: reduce_result_buff = buffer_create_with_protocol(TEMP_NOT_FOUND); uint32_t i,amount_temps = 0; result = receive_int_in_order(socket_nodo, &amount_temps); buffer_add_int(reduce_result_buff, amount_temps); for(i=0;(i<amount_temps) && (result > 0); i++) { uint32_t id_nodo = 0; result = receive_int_in_order(socket_nodo, &id_nodo); if(reduce_dest->prot == ORDER_REDUCE) { buffer_add_int(reduce_result_buff, id_nodo); } char* path = NULL; result = (result > 0) ? receive_dinamic_array_in_order(socket_nodo, (void **) &path) : result; if(path != NULL) { buffer_add_string(reduce_result_buff, path); free(path); } } if(result <= 0) { buffer_destroy(reduce_result_buff); reduce_result_buff = buffer_create_with_protocol(REDUCE_NOT_OK); } break; default: reduce_result_buff = buffer_create_with_protocol(REDUCE_NOT_OK); break; } if((socket_nodo != -1) && (result > 0)) { close(socket_nodo); } pthread_mutex_lock(&conex_marta_ready); result = (result > 0) ? send_buffer_and_destroy(socket_marta, reduce_result_buff) : result; pthread_mutex_unlock(&conex_marta_ready); free(ip_nodo); free_reduce_nodo_dest(nodo_host); free_reduce_dest(reduce_dest); }
/* * Set a given bbox matching a feature collection's outerboundaries * or a simple feature's outerboundaries * Bbox is set from a list containing one or several layer names * and optionnaly one or several WHERE SQL statement following each layer name */ ows_bbox *ows_bbox_boundaries(ows * o, list * from, list * where, ows_srs * srs) { ows_bbox *bb; buffer *sql; list *geom; list_node *ln_from, *ln_where, *ln_geom; PGresult *res; assert(o); assert(from); assert(where); assert(srs); bb = ows_bbox_init(); if (from->size != where->size) return bb; sql = buffer_init(); /* Put into a buffer the SQL request calculating an extent */ buffer_add_str(sql, "SELECT ST_xmin(g.extent), ST_ymin(g.extent), ST_xmax(g.extent), ST_ymax(g.extent) FROM "); buffer_add_str(sql, "(SELECT ST_Extent(foo.the_geom) as extent FROM ( "); /* For each layer name or each geometry column, make an union between retrieved features */ for (ln_from = from->first, ln_where = where->first; ln_from ; ln_from = ln_from->next, ln_where = ln_where->next) { geom = ows_psql_geometry_column(o, ln_from->value); for (ln_geom = geom->first ; ln_geom ; ln_geom = ln_geom->next) { buffer_add_str(sql, " (SELECT ST_Transform(\""); buffer_copy(sql, ln_geom->value); buffer_add_str(sql, "\"::geometry, "); buffer_add_int(sql, srs->srid); buffer_add_str(sql, ") AS \"the_geom\" FROM "); buffer_copy(sql, ows_psql_schema_name(o, ln_from->value)); buffer_add_str(sql, ".\""); buffer_copy(sql, ows_psql_table_name(o, ln_from->value)); buffer_add_str(sql, "\" "); buffer_copy(sql, ln_where->value); buffer_add_str(sql, ")"); if (ln_geom->next) buffer_add_str(sql, " UNION ALL "); } if (ln_from->next) buffer_add_str(sql, " UNION ALL "); } buffer_add_str(sql, " ) AS foo) AS g"); res = ows_psql_exec(o, sql->buf); buffer_free(sql); if (PQresultStatus(res) != PGRES_TUPLES_OK && PQntuples(res) != 4) { PQclear(res); return bb; } bb->xmin = strtod(PQgetvalue(res, 0, 0), NULL); bb->ymin = strtod(PQgetvalue(res, 0, 1), NULL); bb->xmax = strtod(PQgetvalue(res, 0, 2), NULL); bb->ymax = strtod(PQgetvalue(res, 0, 3), NULL); /* TODO Error handling */ ows_srs_copy(bb->srs, srs); PQclear(res); return bb; }
/* * Specifies the list of feature types available from the wfs * Used for both 1.0.0 && 1.1.0 versions */ static void wfs_feature_type_list(ows * o) { ows_layer_node *ln; ows_geobbox *gb; int srid_int; buffer *srid; buffer *srs; list_node *keyword, *l_srid; int s; bool writable, retrievable; assert(o); writable = false; retrievable = false; fprintf(o->output, " <FeatureTypeList>\n"); /* print global operations */ if ( ows_layer_list_retrievable(o->layers) || ows_layer_list_writable(o->layers)) fprintf(o->output, " <Operations>\n"); if (ows_layer_list_retrievable(o->layers)) { if (ows_version_get(o->request->version) == 100) fprintf(o->output, " <Query/>\n"); else if (ows_version_get(o->request->version) == 110) fprintf(o->output, " <Operation>Query</Operation>\n"); retrievable = true; } if (ows_layer_list_writable(o->layers)) { if (ows_version_get(o->request->version) == 100) { fprintf(o->output, " <Insert/>\n"); fprintf(o->output, " <Update/>\n"); fprintf(o->output, " <Delete/>\n"); } else if (ows_version_get(o->request->version) == 110) { fprintf(o->output, " <Operation>Insert</Operation>\n"); fprintf(o->output, " <Operation>Update</Operation>\n"); fprintf(o->output, " <Operation>Delete</Operation>\n"); } writable = true; } if ( ows_layer_list_retrievable(o->layers) || ows_layer_list_writable(o->layers)) fprintf(o->output, " </Operations>\n"); for (ln = o->layers->first ; ln ; ln = ln->next) { /* print each feature type */ if (ows_layer_match_table(o, ln->layer->name)) { fprintf(o->output, "<FeatureType xmlns:%s=\"%s\">\n", ln->layer->ns_prefix->buf, ln->layer->ns_uri->buf); /* name */ if (ln->layer->name) { for (s = 0; s < ln->layer->depth; s++) fprintf(o->output, " "); fprintf(o->output, " <Name>"); buffer_flush(ows_layer_uri_to_prefix(o->layers, ln->layer->name), o->output); fprintf(o->output, "</Name>\n"); } /* title */ if (ln->layer->title) { for (s = 0; s < ln->layer->depth; s++) fprintf(o->output, " "); fprintf(o->output, " <Title>"); buffer_flush(ln->layer->title, o->output); fprintf(o->output, "</Title>\n"); } /* abstract */ if (ln->layer->abstract) { for (s = 0; s < ln->layer->depth; s++) fprintf(o->output, " "); fprintf(o->output, " <Abstract>"); buffer_flush(ln->layer->abstract, o->output); fprintf(o->output, "</Abstract>\n"); } /* keywords */ if (ln->layer->keywords) { for (s = 0; s < ln->layer->depth; s++) fprintf(o->output, " "); fprintf(o->output, " <Keywords>"); for (keyword = ln->layer->keywords->first ; keyword ; keyword = keyword->next) { if (ows_version_get(o->request->version) == 100) { fprintf(o->output, "%s", keyword->value->buf); if (keyword->next) fprintf(o->output, ","); } else if (ows_version_get(o->request->version) == 110) { fprintf(o->output, " <Keyword>"); fprintf(o->output, "%s", keyword->value->buf); fprintf(o->output, "</Keyword>"); } } fprintf(o->output, "</Keywords>\n"); } /* SRS */ srid = buffer_init(); srid_int = ows_srs_get_srid_from_layer(o, ln->layer->name); buffer_add_int(srid, srid_int); srs = ows_srs_get_from_a_srid(o, srid_int); if (srs->use) { if (ows_version_get(o->request->version) == 100) { fprintf(o->output, " <SRS>"); buffer_flush(srs, o->output); fprintf(o->output, "</SRS>\n"); } else if (ows_version_get(o->request->version) == 110) { fprintf(o->output, " <DefaultSRS>urn:ogc:def:crs:EPSG::%s</DefaultSRS>\n", srid->buf); if (ln->layer->srid) { for (l_srid = ln->layer->srid->first; l_srid; l_srid = l_srid->next) { if (!buffer_cmp(srid, l_srid->value->buf)) { fprintf(o->output, " <OtherSRS>urn:ogc:def:crs:EPSG::%s</OtherSRS>\n", l_srid->value->buf); } } } } } else { if (ows_version_get(o->request->version) == 100) fprintf(o->output, " <SRS></SRS>\n"); else if (ows_version_get(o->request->version) == 110) fprintf(o->output, " <NoSRS/>"); } /* Operations */ if (retrievable != ln->layer->retrievable || writable != ln->layer->writable) { fprintf(o->output, " <Operations>\n"); if (retrievable == false && ln->layer->retrievable == true) { if (ows_version_get(o->request->version) == 100) fprintf(o->output, " <Query/>\n"); else if (ows_version_get(o->request->version) == 110) fprintf(o->output, " <Operation>Query</Operation>\n"); } if (writable == false && ln->layer->writable == true) { if (ows_version_get(o->request->version) == 100) { fprintf(o->output, " <Insert/>\n"); fprintf(o->output, " <Update/>\n"); fprintf(o->output, " <Delete/>\n"); } else if (ows_version_get(o->request->version) == 110) { fprintf(o->output, " <Operation>Insert</Operation>\n"); fprintf(o->output, " <Operation>Update</Operation>\n"); fprintf(o->output, " <Operation>Delete</Operation>\n"); } } fprintf(o->output, " </Operations>\n"); } /* Boundaries */ if (!ln->layer->geobbox) { gb = ows_geobbox_compute(o, ln->layer->name); } else { gb = ows_geobbox_init(); gb->west = ln->layer->geobbox->west; gb->east = ln->layer->geobbox->east; gb->south = ln->layer->geobbox->south; gb->north = ln->layer->geobbox->north; } assert(gb); for (s = 0; s < ln->layer->depth; s++) fprintf(o->output, " "); if (ows_version_get(o->request->version) == 100) fprintf(o->output, " <LatLongBoundingBox"); else if (ows_version_get(o->request->version) == 110) fprintf(o->output, " <ows:WGS84BoundingBox>"); if (gb->east != DBL_MIN) { if (ows_version_get(o->request->version) == 100) { if (gb->west < gb->east) fprintf(o->output, " minx='%.*f'", o->degree_precision, gb->west); else fprintf(o->output, " minx='%.*f'", o->degree_precision, gb->east); if (gb->north < gb->south) fprintf(o->output, " miny='%.*f'", o->degree_precision, gb->north); else fprintf(o->output, " miny='%.*f'", o->degree_precision, gb->south); if (gb->west < gb->east) fprintf(o->output, " maxx='%.*f'", o->degree_precision, gb->east); else fprintf(o->output, " maxx='%.*f'", o->degree_precision, gb->west); if (gb->north < gb->south) fprintf(o->output, " maxy='%.*f'", o->degree_precision, gb->south); else fprintf(o->output, " maxy='%.*f'", o->degree_precision, gb->north); fprintf(o->output, " />\n"); } else if (ows_version_get(o->request->version) == 110) { fprintf(o->output, " <ows:LowerCorner>%.*f %.*f</ows:LowerCorner>", o->degree_precision, gb->west, o->degree_precision, gb->south); fprintf(o->output, " <ows:UpperCorner>%.*f %.*f</ows:UpperCorner>", o->degree_precision, gb->east, o->degree_precision, gb->north); } } else { if (ows_version_get(o->request->version) == 100) { fprintf(o->output, " minx='0' miny='0' maxx='0' maxy='0'/>\n"); } else if (ows_version_get(o->request->version) == 110) { fprintf(o->output, " <ows:LowerCorner>0 0</ows:LowerCorner>"); fprintf(o->output, " <ows:UpperCorner>0 0</ows:UpperCorner>"); } } if (ows_version_get(o->request->version) == 110) fprintf(o->output, " </ows:WGS84BoundingBox>\n"); buffer_free(srid); buffer_free(srs); ows_geobbox_free(gb); fprintf(o->output, "</FeatureType>\n"); } } fprintf(o->output, " </FeatureTypeList>\n"); }