mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-02 00:49:33 +02:00
830 lines
27 KiB
C
830 lines
27 KiB
C
/* -*- Mode: c; c-basic-offset: 2 -*-
|
|
*
|
|
* raptor_serialize_dot.c - Serialize RDF graph to GraphViz DOT format
|
|
*
|
|
* Copyright (C) 2004-2007, David Beckett http://www.dajobe.org/
|
|
* Copyright (C) 2004-2005, University of Bristol, UK http://www.bristol.ac.uk/
|
|
*
|
|
* This package is Free Software and part of Redland http://librdf.org/
|
|
*
|
|
* It is licensed under the following three licenses as alternatives:
|
|
* 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
|
|
* 2. GNU General Public License (GPL) V2 or any newer version
|
|
* 3. Apache License, V2.0 or any newer version
|
|
*
|
|
* You may not use this file except in compliance with at least one of
|
|
* the above three licenses.
|
|
*
|
|
* See LICENSE.html or LICENSE.txt at the top of this package for the
|
|
* complete terms and further detail along with the license texts for
|
|
* the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <raptor_config.h>
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
#include <win32_raptor_config.h>
|
|
#endif
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdarg.h>
|
|
#ifdef HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#endif
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
|
|
/* Raptor includes */
|
|
#include "raptor.h"
|
|
#include "raptor_internal.h"
|
|
|
|
/*
|
|
* Raptor dot serializer object
|
|
*/
|
|
typedef struct {
|
|
raptor_namespace_stack *nstack;
|
|
raptor_sequence *namespaces;
|
|
|
|
raptor_sequence *resources;
|
|
raptor_sequence *literals;
|
|
raptor_sequence *bnodes;
|
|
} raptor_dot_context;
|
|
|
|
typedef struct {
|
|
raptor_identifier_type type; /* node type */
|
|
union {
|
|
|
|
struct {
|
|
raptor_uri *uri;
|
|
} resource;
|
|
|
|
struct {
|
|
unsigned char *string;
|
|
raptor_uri *datatype;
|
|
unsigned char *language;
|
|
} literal;
|
|
|
|
struct {
|
|
unsigned char *string;
|
|
} blank;
|
|
|
|
} value;
|
|
} raptor_dot_serializer_node;
|
|
|
|
|
|
/* Free a node */
|
|
static void
|
|
raptor_dot_serializer_free_node(raptor_dot_serializer_node *node)
|
|
{
|
|
if(!node)
|
|
return;
|
|
|
|
switch (node->type) {
|
|
case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
|
|
case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
|
|
raptor_free_uri(node->value.resource.uri);
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
|
|
RAPTOR_FREE(blank, node->value.blank.string);
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_LITERAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
|
|
RAPTOR_FREE(literal, node->value.literal.string);
|
|
|
|
if(node->value.literal.datatype)
|
|
raptor_free_uri(node->value.literal.datatype);
|
|
|
|
if(node->value.literal.language)
|
|
RAPTOR_FREE(language, node->value.literal.language);
|
|
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
|
|
default:
|
|
/* Nothing to do */
|
|
break;
|
|
}
|
|
|
|
RAPTOR_FREE(raptor_node, node);
|
|
}
|
|
|
|
|
|
/*
|
|
* raptor_dot_serializer_node_matches:
|
|
* @node: #raptor_node to compare
|
|
* @node_type: Raptor identifier type
|
|
* @node_data: For node_type RAPTOR_IDENTIFIER_TYPE_ORDINAL, int* to the
|
|
* ordinal.
|
|
* @datatype: Literal datatype or NULL
|
|
* @language: Literal language or NULL
|
|
*
|
|
* Return value: non-zero if @node matches the node described by the rest of
|
|
* the parameters.
|
|
*/
|
|
static int
|
|
raptor_dot_serializer_node_matches(raptor_dot_serializer_node* node,
|
|
raptor_identifier_type node_type,
|
|
const void* node_data, raptor_uri* datatype,
|
|
const unsigned char* language)
|
|
{
|
|
int rv = 0;
|
|
|
|
if(node->type != node_type)
|
|
return 0;
|
|
|
|
switch (node->type) {
|
|
case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
|
|
case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
|
|
rv = raptor_uri_equals(node->value.resource.uri,
|
|
(raptor_uri*)node_data);
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
|
|
rv = !strcmp((const char*)node->value.blank.string,
|
|
(const char*)node_data);
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_LITERAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
|
|
|
|
if((char*)node->value.literal.string != NULL &&
|
|
(char*)node_data != NULL) {
|
|
|
|
/* string */
|
|
rv = (strcmp((char*)node->value.literal.string,
|
|
(char*)node_data) == 0);
|
|
|
|
/* language */
|
|
if((char*)node->value.literal.language != NULL &&
|
|
(char*)language != NULL)
|
|
rv &= (strcmp((char*)node->value.literal.language,
|
|
(char*)language) == 0);
|
|
else if((char*)node->value.literal.language != NULL ||
|
|
(char*)language != NULL)
|
|
rv= 0;
|
|
|
|
/* datatype */
|
|
if(node->value.literal.datatype != NULL && datatype != NULL)
|
|
rv &= (raptor_uri_equals(node->value.literal.datatype,datatype) !=0);
|
|
else if(node->value.literal.datatype != NULL || datatype != NULL)
|
|
rv = 0;
|
|
|
|
} else {
|
|
RAPTOR_FATAL1("string must be non-NULL for literal or xml literal\n");
|
|
rv = 0;
|
|
}
|
|
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
|
|
default:
|
|
/* Nothing to do */
|
|
break;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
/*
|
|
* raptor_dot_serializer_new_node implementation:
|
|
* @node_type: Raptor identifier type
|
|
* @node_data: For node_type RAPTOR_IDENTIFIER_TYPE_ORDINAL, int* to the
|
|
* ordinal.
|
|
* @datatype: Literal datatype or NULL
|
|
* @language: Literal language or NULL
|
|
*
|
|
* Parts of this is taken from redland librdf_node.h and librdf_node.c
|
|
*
|
|
* Return value: a new raptor_dot_serializer_node
|
|
*
|
|
**/
|
|
static raptor_dot_serializer_node *
|
|
raptor_dot_serializer_new_node(raptor_identifier_type node_type,
|
|
const void* node_data,
|
|
raptor_uri* datatype,
|
|
const unsigned char *language)
|
|
{
|
|
unsigned char *string;
|
|
raptor_dot_serializer_node* node;
|
|
|
|
if(node_type == RAPTOR_IDENTIFIER_TYPE_UNKNOWN)
|
|
return NULL;
|
|
|
|
node = (raptor_dot_serializer_node *)RAPTOR_CALLOC(raptor_dot_serializer_node, 1, sizeof(raptor_dot_serializer_node));
|
|
|
|
if(node) {
|
|
node->type = node_type;
|
|
|
|
switch (node_type) {
|
|
case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
|
|
node->type = RAPTOR_IDENTIFIER_TYPE_RESOURCE;
|
|
/* intentional fall through */
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
|
|
node->value.resource.uri = raptor_uri_copy((raptor_uri*)node_data);
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
|
|
string=(unsigned char*)RAPTOR_MALLOC(blank,
|
|
strlen((char*)node_data)+1);
|
|
strcpy((char*)string, (const char*) node_data);
|
|
node->value.blank.string = string;
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_LITERAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
|
|
string = (unsigned char*)RAPTOR_MALLOC(literal,
|
|
strlen((char*)node_data)+1);
|
|
strcpy((char*)string, (const char*)node_data);
|
|
node->value.literal.string = string;
|
|
|
|
if(datatype)
|
|
node->value.literal.datatype = raptor_uri_copy(datatype);
|
|
|
|
if(language) {
|
|
unsigned char *lang;
|
|
lang = (unsigned char*)RAPTOR_MALLOC(language,
|
|
strlen((const char*)language)+1);
|
|
strcpy((char*)lang, (const char*)language);
|
|
node->value.literal.language = lang;
|
|
}
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
|
|
default:
|
|
RAPTOR_FREE(raptor_dot_serializer_node, node);
|
|
}
|
|
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
/* add a namespace */
|
|
static int
|
|
raptor_dot_serializer_declare_namespace_from_namespace(raptor_serializer* serializer,
|
|
raptor_namespace *nspace)
|
|
{
|
|
raptor_dot_context * context = (raptor_dot_context *)serializer->context;
|
|
int i;
|
|
|
|
for( i = 0 ; i < raptor_sequence_size(context->namespaces) ; i++ ) {
|
|
raptor_namespace * ns;
|
|
ns = (raptor_namespace *)raptor_sequence_get_at(context->namespaces, i);
|
|
|
|
/* If prefix is already declared, ignore it */
|
|
if((!ns->prefix && !nspace->prefix) ||
|
|
(ns->prefix && nspace->prefix &&
|
|
!strcmp((const char*)ns->prefix, (const char*)nspace->prefix)) ||
|
|
(ns->uri && nspace->uri &&
|
|
raptor_uri_equals(ns->uri, nspace->uri)) )
|
|
return 1;
|
|
}
|
|
|
|
nspace = raptor_new_namespace_from_uri(context->nstack, nspace->prefix,
|
|
nspace->uri, 0);
|
|
|
|
if(!nspace)
|
|
return 1;
|
|
|
|
raptor_sequence_push(context->namespaces, nspace);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* add a namespace */
|
|
static int
|
|
raptor_dot_serializer_declare_namespace(raptor_serializer* serializer,
|
|
raptor_uri* uri,
|
|
const unsigned char *prefix)
|
|
{
|
|
raptor_dot_context * context = (raptor_dot_context *)serializer->context;
|
|
raptor_namespace *ns;
|
|
int rc;
|
|
|
|
ns = raptor_new_namespace_from_uri(context->nstack, prefix, uri, 0);
|
|
rc = raptor_dot_serializer_declare_namespace_from_namespace(serializer, ns);
|
|
|
|
raptor_free_namespace(ns);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/* create a new serializer */
|
|
static int
|
|
raptor_dot_serializer_init(raptor_serializer *serializer, const char *name)
|
|
{
|
|
raptor_dot_context * context = (raptor_dot_context *)serializer->context;
|
|
const raptor_uri_handler *uri_handler;
|
|
void* uri_context;
|
|
|
|
raptor_uri_get_handler(&uri_handler, &uri_context);
|
|
|
|
/* Setup namespace handling */
|
|
context->nstack =
|
|
raptor_new_namespaces(uri_handler, uri_context,
|
|
(raptor_simple_message_handler)raptor_serializer_simple_error,
|
|
serializer, 1);
|
|
context->namespaces=raptor_new_sequence((raptor_sequence_free_handler *)raptor_free_namespace, NULL);
|
|
|
|
/* We keep a list of nodes to avoid duplication (which isn't
|
|
* critical in graphviz, but why bloat the file?)
|
|
*/
|
|
context->resources =
|
|
raptor_new_sequence((raptor_sequence_free_handler *)raptor_dot_serializer_free_node, NULL);
|
|
context->literals =
|
|
raptor_new_sequence((raptor_sequence_free_handler *)raptor_dot_serializer_free_node, NULL);
|
|
context->bnodes =
|
|
raptor_new_sequence((raptor_sequence_free_handler *)raptor_dot_serializer_free_node, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
* raptor_dot_iostream_write_string:
|
|
* @iostr: #raptor_iostream to write to
|
|
* @string: UTF-8 string to write
|
|
* @len: length of UTF-8 string
|
|
* or \0 for no escaping.
|
|
*
|
|
* Write an UTF-8 string, escaped for graphviz.
|
|
*
|
|
* Return value: non-0 on failure.
|
|
**/
|
|
static int
|
|
raptor_dot_iostream_write_string(raptor_iostream *iostr,
|
|
const unsigned char *string)
|
|
{
|
|
unsigned char c;
|
|
|
|
for( ; (c = *string) ; string++ ) {
|
|
if( (c == '\\') || (c == '"') || (c == '|') ||
|
|
(c == '{') || (c == '}') ) {
|
|
raptor_iostream_write_byte(iostr, '\\');
|
|
raptor_iostream_write_byte(iostr, c);
|
|
} else if( c == '\n' ) {
|
|
raptor_iostream_write_byte(iostr, '\\');
|
|
raptor_iostream_write_byte(iostr, 'n');
|
|
} else
|
|
raptor_iostream_write_byte(iostr, c);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
raptor_dot_serializer_write_node_type(raptor_serializer * serializer,
|
|
raptor_identifier_type type)
|
|
{
|
|
switch(type) {
|
|
case RAPTOR_IDENTIFIER_TYPE_LITERAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
|
|
raptor_iostream_write_byte(serializer->iostream, 'L');
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
|
|
raptor_iostream_write_byte(serializer->iostream, 'B');
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
|
|
case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
|
|
raptor_iostream_write_byte(serializer->iostream, 'R');
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
|
|
raptor_iostream_write_byte(serializer->iostream, '?');
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
raptor_dot_serializer_write_uri(raptor_serializer* serializer,
|
|
raptor_uri* uri)
|
|
{
|
|
raptor_dot_context* context = (raptor_dot_context*)serializer->context;
|
|
unsigned char* full = raptor_uri_as_string(uri);
|
|
int i;
|
|
|
|
for( i = 0 ; i < raptor_sequence_size(context->namespaces) ; i++ ) {
|
|
raptor_namespace* ns =
|
|
(raptor_namespace*)raptor_sequence_get_at(context->namespaces, i);
|
|
const unsigned char* ns_uri_string;
|
|
size_t ns_uri_string_len;
|
|
ns_uri_string=raptor_uri_as_counted_string(ns->uri, &ns_uri_string_len);
|
|
|
|
if(!strncmp((char*)full, (char*)ns_uri_string, ns_uri_string_len) ) {
|
|
const unsigned char* prefix = raptor_namespace_get_prefix(ns);
|
|
|
|
if(prefix) {
|
|
raptor_iostream_write_string(serializer->iostream, prefix);
|
|
raptor_iostream_write_byte(serializer->iostream, ':');
|
|
}
|
|
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
full + ns_uri_string_len);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
raptor_iostream_write_string(serializer->iostream, full);
|
|
}
|
|
|
|
|
|
static void
|
|
raptor_dot_serializer_write_node(raptor_serializer * serializer,
|
|
const void* term,
|
|
raptor_identifier_type type,
|
|
raptor_uri* literal_datatype,
|
|
const unsigned char * literal_language) {
|
|
switch(type) {
|
|
case RAPTOR_IDENTIFIER_TYPE_LITERAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
|
|
raptor_dot_iostream_write_string(serializer->iostream, (const unsigned char*)term);
|
|
if(literal_language && type == RAPTOR_IDENTIFIER_TYPE_LITERAL) {
|
|
raptor_iostream_write_byte(serializer->iostream, '|');
|
|
raptor_iostream_write_string(serializer->iostream, "Language: ");
|
|
raptor_iostream_write_string(serializer->iostream, literal_language);
|
|
}
|
|
if(type == RAPTOR_IDENTIFIER_TYPE_XML_LITERAL) {
|
|
raptor_iostream_write_byte(serializer->iostream, '|');
|
|
raptor_iostream_write_string(serializer->iostream, "Datatype: ");
|
|
raptor_iostream_write_string(serializer->iostream, raptor_xml_literal_datatype_uri_string);
|
|
} else if(literal_datatype) {
|
|
raptor_iostream_write_byte(serializer->iostream, '|');
|
|
raptor_iostream_write_string(serializer->iostream, "Datatype: ");
|
|
raptor_dot_serializer_write_uri(serializer, (raptor_uri*)literal_datatype);
|
|
}
|
|
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
|
|
raptor_iostream_write_counted_string(serializer->iostream, "_:", 2);
|
|
raptor_iostream_write_string(serializer->iostream, term);
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
|
|
case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
|
|
raptor_dot_serializer_write_uri(serializer, (raptor_uri*)term);
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
|
|
default:
|
|
RAPTOR_FATAL2("Unknown type %d", type);
|
|
}
|
|
}
|
|
|
|
|
|
/* Check the list to see if the node is a duplicate. If not, add it
|
|
* to the list.
|
|
*/
|
|
static void
|
|
raptor_dot_serializer_assert_node(raptor_serializer* serializer,
|
|
raptor_identifier_type node_type,
|
|
const void* node_data,
|
|
raptor_uri* datatype,
|
|
const unsigned char* language)
|
|
{
|
|
raptor_dot_context* context = (raptor_dot_context*)serializer->context;
|
|
raptor_sequence* seq = NULL;
|
|
int i;
|
|
|
|
/* Which list are we searching? */
|
|
switch(node_type) {
|
|
case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
|
|
case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
|
|
seq = context->resources;
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
|
|
seq = context->bnodes;
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_LITERAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
|
|
seq = context->literals;
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
|
|
case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
|
|
break;
|
|
}
|
|
|
|
for( i = 0 ; i < raptor_sequence_size(seq) ; i++ ) {
|
|
raptor_dot_serializer_node* node =
|
|
(raptor_dot_serializer_node*)raptor_sequence_get_at(seq, i);
|
|
|
|
if(raptor_dot_serializer_node_matches(node, node_type, node_data,
|
|
datatype, language) )
|
|
return;
|
|
}
|
|
|
|
raptor_sequence_push(seq,
|
|
raptor_dot_serializer_new_node(node_type, node_data,
|
|
datatype, language));
|
|
}
|
|
|
|
|
|
/* start a serialize */
|
|
static int
|
|
raptor_dot_serializer_start(raptor_serializer* serializer)
|
|
{
|
|
raptor_iostream_write_string(serializer->iostream, (const unsigned char *)
|
|
"digraph {\n\trankdir=LR;\n\tcharset=\"utf-8\";\n\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
raptor_dot_serializer_write_colors(raptor_serializer* serializer,
|
|
raptor_identifier_type type)
|
|
{
|
|
switch(type) {
|
|
case RAPTOR_IDENTIFIER_TYPE_RESOURCE:
|
|
if(serializer->feature_resource_border) {
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)", color=");
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)serializer->feature_resource_border);
|
|
}
|
|
else
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)", color=blue");
|
|
|
|
if(serializer->feature_resource_fill) {
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)", style=filled, fillcolor=");
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)
|
|
serializer->feature_resource_fill);
|
|
}
|
|
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_ANONYMOUS:
|
|
if(serializer->feature_bnode_border) {
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)", color=");
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)serializer->feature_bnode_border);
|
|
}
|
|
else
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)", color=green");
|
|
|
|
if(serializer->feature_bnode_fill) {
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)", style=filled, fillcolor=");
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)serializer->feature_bnode_fill);
|
|
}
|
|
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_LITERAL:
|
|
if(serializer->feature_literal_border) {
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)", color=");
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)serializer->feature_literal_border);
|
|
}
|
|
|
|
if(serializer->feature_literal_fill) {
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)", style=filled, fillcolor=");
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)serializer->feature_literal_fill);
|
|
}
|
|
|
|
break;
|
|
|
|
case RAPTOR_IDENTIFIER_TYPE_PREDICATE:
|
|
case RAPTOR_IDENTIFIER_TYPE_ORDINAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_XML_LITERAL:
|
|
case RAPTOR_IDENTIFIER_TYPE_UNKNOWN:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* end a serialize */
|
|
static int
|
|
raptor_dot_serializer_end(raptor_serializer* serializer)
|
|
{
|
|
raptor_dot_context* context=(raptor_dot_context*)serializer->context;
|
|
raptor_dot_serializer_node* node;
|
|
int i;
|
|
|
|
/* Print our nodes. */
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\n\t// Resources\n");
|
|
for( i = 0 ; i < raptor_sequence_size(context->resources) ; i++ ) {
|
|
node = (raptor_dot_serializer_node*)raptor_sequence_get_at(context->resources, i);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\t\"R");
|
|
raptor_dot_serializer_write_node(serializer, node->value.resource.uri,
|
|
RAPTOR_IDENTIFIER_TYPE_RESOURCE, NULL, NULL);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\" [ label=\"");
|
|
raptor_dot_serializer_write_node(serializer, node->value.resource.uri,
|
|
RAPTOR_IDENTIFIER_TYPE_RESOURCE, NULL, NULL);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\", shape=ellipse");
|
|
raptor_dot_serializer_write_colors(serializer,
|
|
RAPTOR_IDENTIFIER_TYPE_RESOURCE);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)" ];\n");
|
|
|
|
}
|
|
raptor_free_sequence(context->resources);
|
|
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\n\t// Anonymous nodes\n");
|
|
for( i = 0 ; i < raptor_sequence_size(context->bnodes) ; i++ ) {
|
|
node = (raptor_dot_serializer_node *)raptor_sequence_get_at(context->bnodes, i);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\t\"B");
|
|
raptor_dot_serializer_write_node(serializer, node->value.resource.uri,
|
|
RAPTOR_IDENTIFIER_TYPE_ANONYMOUS, NULL, NULL);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\" [ label=\"");
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\", shape=circle");
|
|
raptor_dot_serializer_write_colors(serializer,
|
|
RAPTOR_IDENTIFIER_TYPE_ANONYMOUS);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)" ];\n");
|
|
}
|
|
raptor_free_sequence(context->bnodes);
|
|
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\n\t// Literals\n");
|
|
for( i = 0 ; i < raptor_sequence_size(context->literals) ; i++ ) {
|
|
node = (raptor_dot_serializer_node *)raptor_sequence_get_at(context->literals, i);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\t\"L");
|
|
raptor_dot_serializer_write_node(serializer, node->value.literal.string,
|
|
RAPTOR_IDENTIFIER_TYPE_LITERAL,
|
|
node->value.literal.datatype,
|
|
node->value.literal.language);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\" [ label=\"");
|
|
raptor_dot_serializer_write_node(serializer, node->value.literal.string,
|
|
RAPTOR_IDENTIFIER_TYPE_LITERAL,
|
|
node->value.literal.datatype,
|
|
node->value.literal.language);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\", shape=record");
|
|
raptor_dot_serializer_write_colors(serializer,
|
|
RAPTOR_IDENTIFIER_TYPE_LITERAL);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)" ];\n");
|
|
}
|
|
raptor_free_sequence(context->literals);
|
|
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\n\tlabel=\"\\n\\nModel:\\n");
|
|
if(serializer->base_uri)
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
raptor_uri_as_string(serializer->base_uri));
|
|
else
|
|
raptor_iostream_write_string(serializer->iostream, "(Unknown)");
|
|
|
|
if(raptor_sequence_size(context->namespaces)) {
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\\n\\nNamespaces:\\n");
|
|
|
|
for( i = 0 ; i < raptor_sequence_size(context->namespaces) ; i++ ) {
|
|
raptor_namespace* ns =
|
|
(raptor_namespace*)raptor_sequence_get_at(context->namespaces, i);
|
|
const unsigned char* prefix = raptor_namespace_get_prefix(ns);
|
|
|
|
if(prefix) {
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)ns->prefix);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)": ");
|
|
}
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
raptor_uri_as_string(ns->uri));
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\\n");
|
|
}
|
|
|
|
raptor_free_sequence(context->namespaces);
|
|
}
|
|
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\";\n");
|
|
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *) "}\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* destroy a serializer */
|
|
static void
|
|
raptor_dot_serializer_terminate(raptor_serializer* serializer)
|
|
{
|
|
/* raptor_dot_context* context=(raptor_dot_context*)serializer->context; */
|
|
|
|
/* Everything should have been freed in raptor_dot_serializer_end */
|
|
}
|
|
|
|
/* serialize a statement */
|
|
static int
|
|
raptor_dot_serializer_statement(raptor_serializer* serializer,
|
|
const raptor_statement *statement)
|
|
{
|
|
/* Cache the nodes for later. */
|
|
raptor_dot_serializer_assert_node(serializer, statement->subject_type,
|
|
statement->subject, NULL, NULL);
|
|
raptor_dot_serializer_assert_node(serializer, statement->object_type,
|
|
statement->object, statement->object_literal_datatype,
|
|
statement->object_literal_language);
|
|
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\t\"");
|
|
raptor_dot_serializer_write_node_type(serializer, statement->subject_type);
|
|
raptor_dot_serializer_write_node(serializer,
|
|
statement->subject,
|
|
statement->subject_type,
|
|
NULL, NULL);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\" -> \"");
|
|
raptor_dot_serializer_write_node_type(serializer, statement->object_type);
|
|
raptor_dot_serializer_write_node(serializer,
|
|
statement->object,
|
|
statement->object_type,
|
|
statement->object_literal_datatype,
|
|
statement->object_literal_language);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\" [ label=\"");
|
|
raptor_dot_serializer_write_node(serializer,
|
|
statement->predicate,
|
|
statement->predicate_type,
|
|
NULL, NULL);
|
|
raptor_iostream_write_string(serializer->iostream,
|
|
(const unsigned char *)"\" ];\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
raptor_dot_serializer_register_factory(raptor_serializer_factory *factory)
|
|
{
|
|
factory->context_length = sizeof(raptor_dot_context);
|
|
|
|
factory->init = raptor_dot_serializer_init;
|
|
factory->declare_namespace = raptor_dot_serializer_declare_namespace;
|
|
factory->declare_namespace_from_namespace =
|
|
raptor_dot_serializer_declare_namespace_from_namespace;
|
|
factory->serialize_start = raptor_dot_serializer_start;
|
|
factory->serialize_statement = raptor_dot_serializer_statement;
|
|
factory->serialize_end = raptor_dot_serializer_end;
|
|
factory->finish_factory = NULL;
|
|
factory->terminate = raptor_dot_serializer_terminate;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
raptor_init_serializer_dot (void)
|
|
{
|
|
return raptor_serializer_register_factory("dot",
|
|
"GraphViz DOT format",
|
|
"text/x-graphviz",
|
|
NULL,
|
|
(const unsigned char*)"http://www.graphviz.org/doc/info/lang.html",
|
|
&raptor_dot_serializer_register_factory);
|
|
}
|