correct edge source/target nodes constuction

This commit is contained in:
Alexey Fedoseev
2024-01-08 23:26:45 +03:00
parent 6258117906
commit d78e581306
2 changed files with 83 additions and 51 deletions

View File

@@ -135,12 +135,14 @@ static CyberiadaNode* cyberiada_new_node(const char* id)
return new_node; return new_node;
} }
static CyberiadaEdge* cyberiada_new_edge(const char* id, CyberiadaNode* source, CyberiadaNode* target) static CyberiadaEdge* cyberiada_new_edge(const char* id, const char* source, const char* target)
{ {
CyberiadaEdge* new_edge = (CyberiadaEdge*)malloc(sizeof(CyberiadaEdge)); CyberiadaEdge* new_edge = (CyberiadaEdge*)malloc(sizeof(CyberiadaEdge));
cyberiada_copy_string(&(new_edge->id), &(new_edge->id_len), id); cyberiada_copy_string(&(new_edge->id), &(new_edge->id_len), id);
new_edge->source = source; cyberiada_copy_string(&(new_edge->source_id), &(new_edge->source_id_len), source);
new_edge->target = target; cyberiada_copy_string(&(new_edge->target_id), &(new_edge->target_id_len), target);
new_edge->source = NULL;
new_edge->target = NULL;
new_edge->action = NULL; new_edge->action = NULL;
new_edge->next = NULL; new_edge->next = NULL;
new_edge->geometry_source_point.x = new_edge->geometry_source_point.y = new_edge->geometry_source_point.x = new_edge->geometry_source_point.y =
@@ -161,7 +163,7 @@ static int cyberiada_graph_add_sibling_node(CyberiadaNode* sibling, CyberiadaNod
return CYBERIADA_NO_ERROR; return CYBERIADA_NO_ERROR;
} }
static int cyberiada_graph_add_edge(CyberiadaSM* sm, const char* id, CyberiadaNode* source, CyberiadaNode* target) static int cyberiada_graph_add_edge(CyberiadaSM* sm, const char* id, const char* source, const char* target)
{ {
CyberiadaEdge* last_edge; CyberiadaEdge* last_edge;
CyberiadaEdge* new_edge; CyberiadaEdge* new_edge;
@@ -190,6 +192,23 @@ static CyberiadaEdge* cyberiada_graph_find_last_edge(CyberiadaSM* sm)
return edge; return edge;
} }
static int cyberiada_graph_reconstruct_edges(CyberiadaSM* sm)
{
CyberiadaEdge* edge = sm->edges;
while (edge) {
CyberiadaNode* source = cyberiada_graph_find_node(sm->nodes, edge->source_id);
CyberiadaNode* target = cyberiada_graph_find_node(sm->nodes, edge->target_id);
if (!source || !target) {
fprintf(stderr, "cannot find source/target node for edge %s\n", edge->id);
return CYBERIADA_FORMAT_ERROR;
}
edge->source = source;
edge->target = target;
edge = edge->next;
}
return CYBERIADA_NO_ERROR;
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* The Cyberiada GraphML library fucntions declarations * The Cyberiada GraphML library fucntions declarations
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
@@ -667,36 +686,30 @@ static GraphProcessorState handle_new_edge(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaSM* sm,
NodeStack** stack) NodeStack** stack)
{ {
CyberiadaNode* source = NULL;
CyberiadaNode* target = NULL;
char buffer[MAX_STR_LEN]; char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1; size_t buffer_len = sizeof(buffer) - 1;
if(cyberiada_get_attr_value(buffer, buffer_len, char source_buffer[MAX_STR_LEN];
xml_node, size_t source_buffer_len = sizeof(source_buffer) - 1;
GRAPHML_SOURCE_ATTRIBUTE) != CYBERIADA_NO_ERROR) { char target_buffer[MAX_STR_LEN];
return gpsInvalid; size_t target_buffer_len = sizeof(target_buffer) - 1;
}
source = cyberiada_graph_find_node(sm->nodes, buffer);
if (source == NULL) {
return gpsInvalid;
}
if(cyberiada_get_attr_value(buffer, buffer_len,
xml_node,
GRAPHML_TARGET_ATTRIBUTE) != CYBERIADA_NO_ERROR) {
return gpsInvalid;
}
target = cyberiada_graph_find_node(sm->nodes, buffer);
if (target == NULL) {
return gpsInvalid;
}
if(cyberiada_get_attr_value(buffer, buffer_len, if(cyberiada_get_attr_value(buffer, buffer_len,
xml_node, xml_node,
GRAPHML_ID_ATTRIBUTE) != CYBERIADA_NO_ERROR) { GRAPHML_ID_ATTRIBUTE) != CYBERIADA_NO_ERROR) {
buffer[0] = 0; buffer[0] = 0;
} }
DEBUG("found edge %s\n", buffer); DEBUG("found edge %s\n", buffer);
DEBUG("add edge %s %s -> %s\n", buffer, source->id, target->id); if(cyberiada_get_attr_value(source_buffer, source_buffer_len,
cyberiada_graph_add_edge(sm, buffer, source, target); xml_node,
GRAPHML_SOURCE_ATTRIBUTE) != CYBERIADA_NO_ERROR) {
return gpsInvalid;
}
if(cyberiada_get_attr_value(target_buffer, target_buffer_len,
xml_node,
GRAPHML_TARGET_ATTRIBUTE) != CYBERIADA_NO_ERROR) {
return gpsInvalid;
}
DEBUG("add edge %s %s -> %s\n", buffer, source_buffer, target_buffer);
cyberiada_graph_add_edge(sm, buffer, source_buffer, target_buffer);
return gpsEdgePath; return gpsEdgePath;
} }
@@ -773,12 +786,12 @@ static GraphProcessorState handle_edge_label(xmlNode* xml_node,
} }
if (current->action != NULL) { if (current->action != NULL) {
ERROR("Trying to set edge %s:%s label twice\n", ERROR("Trying to set edge %s:%s label twice\n",
current->source->id, current->target->id); current->source_id, current->target_id);
return gpsInvalid; return gpsInvalid;
} }
cyberiada_get_element_text(buffer, buffer_len, xml_node); cyberiada_get_element_text(buffer, buffer_len, xml_node);
DEBUG("add edge %s:%s label %s\n", DEBUG("add edge %s:%s label %s\n",
current->source->id, current->target->id, buffer); current->source_id, current->target_id, buffer);
cyberiada_copy_string(&(current->action), &(current->action_len), buffer); cyberiada_copy_string(&(current->action), &(current->action_len), buffer);
return gpsGraph; return gpsGraph;
} }
@@ -951,29 +964,44 @@ int cyberiada_read_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
return CYBERIADA_XML_ERROR; return CYBERIADA_XML_ERROR;
} }
/* get the root element node */ do {
root = xmlDocGetRootElement(doc); /* get the root element node */
root = xmlDocGetRootElement(doc);
if (strcmp((const char*)root->name, GRAPHML_GRAPHML_ELEMENT) != 0) { if (strcmp((const char*)root->name, GRAPHML_GRAPHML_ELEMENT) != 0) {
ERROR("error: could not find GraphML root node %s\n", filename); ERROR("error: could not find GraphML root node %s\n", filename);
return CYBERIADA_XML_ERROR; res = CYBERIADA_XML_ERROR;
} break;
}
/* check whether the xml is graphml */ /* check whether the xml is graphml */
if (cyberiada_check_graphml_ns(root, &format)) { if (cyberiada_check_graphml_ns(root, &format)) {
ERROR("error: no valid graphml namespace in %s\n", filename); ERROR("error: no valid graphml namespace in %s\n", filename);
return CYBERIADA_XML_ERROR; res = CYBERIADA_XML_ERROR;
} break;
}
if (format == cybxmlYED) { if (format == cybxmlYED) {
res = cyberiada_decode_yed_xml(root, sm); res = cyberiada_decode_yed_xml(root, sm);
} else if (format == cybxmlCyberiada) { } else if (format == cybxmlCyberiada) {
res = cyberiada_decode_cyberiada_xml(root, sm); res = cyberiada_decode_cyberiada_xml(root, sm);
} else { } else {
ERROR("error: unsupported GraphML format of file %s\n", ERROR("error: unsupported GraphML format of file %s\n",
filename); filename);
return CYBERIADA_XML_ERROR; res = CYBERIADA_XML_ERROR;
} break;
}
if (res != CYBERIADA_NO_ERROR) {
break;
}
if ((res = cyberiada_graph_reconstruct_edges(sm)) != CYBERIADA_NO_ERROR) {
ERROR("error: cannot reconstruct graph edges from file %s\n",
filename);
break;
}
} while(0);
xmlFreeDoc(doc); xmlFreeDoc(doc);
xmlCleanupParser(); xmlCleanupParser();
@@ -1021,9 +1049,9 @@ static int cyberiada_print_edge(CyberiadaEdge* edge)
CyberiadaPolyline* polyline; CyberiadaPolyline* polyline;
printf(" Edge %s [%s %s]->[%s %s]\n", printf(" Edge %s [%s %s]->[%s %s]\n",
edge->id, edge->id,
edge->source->id, edge->source_id,
edge->source->type == cybNodeInitial ? "INIT" : edge->source->title, edge->source->type == cybNodeInitial ? "INIT" : edge->source->title,
edge->target->id, edge->target_id,
edge->target->title == cybNodeInitial ? "INIT" : edge->target->title); edge->target->title == cybNodeInitial ? "INIT" : edge->target->title);
if (edge->geometry_polyline == NULL) { if (edge->geometry_polyline == NULL) {
printf(" Geometry: (%lf, %lf)->(%lf, %lf)\n", printf(" Geometry: (%lf, %lf)->(%lf, %lf)\n",

View File

@@ -75,6 +75,10 @@ typedef struct _CyberiadaNode {
typedef struct _CyberiadaEdge { typedef struct _CyberiadaEdge {
char* id; char* id;
size_t id_len; size_t id_len;
char* source_id;
size_t source_id_len;
char* target_id;
size_t target_id_len;
CyberiadaNode* source; CyberiadaNode* source;
CyberiadaNode* target; CyberiadaNode* target;
char* action; char* action;