mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 16:10:06 +02:00
546 lines
17 KiB
C
546 lines
17 KiB
C
/**
|
|
* Copyright 2008 Digital Bazaar, Inc.
|
|
*
|
|
* This file is part of librdfa.
|
|
*
|
|
* librdfa is Free Software, and can be licensed under any of the
|
|
* following three licenses:
|
|
*
|
|
* 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-* at the top of this software distribution for more
|
|
* information regarding the details of each license.
|
|
*
|
|
* Handles all triple functionality including all incomplete triple
|
|
* functionality.
|
|
*
|
|
* @author Manu Sporny
|
|
*/
|
|
#include "stdlib.h"
|
|
#include "string.h"
|
|
#include "stdio.h"
|
|
#include "rdfa_utils.h"
|
|
#include "rdfa.h"
|
|
|
|
rdftriple* rdfa_create_triple(const char* subject, const char* predicate,
|
|
const char* object, rdfresource_t object_type, const char* datatype,
|
|
const char* language)
|
|
{
|
|
rdftriple* rval = (rdftriple*)malloc(sizeof(rdftriple));
|
|
|
|
// clear the memory
|
|
rval->subject = NULL;
|
|
rval->predicate = NULL;
|
|
rval->object = NULL;
|
|
rval->object_type = object_type;
|
|
rval->datatype = NULL;
|
|
rval->language = NULL;
|
|
|
|
//printf("SUBJECT : %s\n", subject);
|
|
//printf("PREDICATE: %s\n", predicate);
|
|
//printf("OBJECT : %s\n", object);
|
|
//printf("DATATYPE : %s\n", datatype);
|
|
//printf("LANG : %s\n", language);
|
|
|
|
// a triple needs a subject, predicate and object at minimum to be
|
|
// considered a triple.
|
|
if((subject != NULL) && (predicate != NULL) && (object != NULL))
|
|
{
|
|
rval->subject = rdfa_replace_string(rval->subject, subject);
|
|
rval->predicate = rdfa_replace_string(rval->predicate, predicate);
|
|
rval->object = rdfa_replace_string(rval->object, object);
|
|
|
|
// if the datatype is present, set it
|
|
if(datatype != NULL)
|
|
{
|
|
rval->datatype = rdfa_replace_string(rval->datatype, datatype);
|
|
}
|
|
|
|
// if the language was specified, set it
|
|
if(language != NULL)
|
|
{
|
|
rval->language = rdfa_replace_string(rval->language, language);
|
|
}
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
void rdfa_print_triple(rdftriple* triple)
|
|
{
|
|
if(triple->object_type == RDF_TYPE_NAMESPACE_PREFIX)
|
|
{
|
|
printf("%s %s: <%s> .\n",
|
|
triple->subject, triple->predicate, triple->object);
|
|
}
|
|
else
|
|
{
|
|
if(triple->subject != NULL)
|
|
{
|
|
if((triple->subject[0] == '_') && (triple->subject[1] == ':'))
|
|
{
|
|
printf("%s\n", triple->subject);
|
|
}
|
|
else
|
|
{
|
|
printf("<%s>\n", triple->subject);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("INCOMPLETE\n");
|
|
}
|
|
|
|
if(triple->predicate != NULL)
|
|
{
|
|
printf(" <%s>\n", triple->predicate);
|
|
}
|
|
else
|
|
{
|
|
printf(" INCOMPLETE\n");
|
|
}
|
|
|
|
if(triple->object != NULL)
|
|
{
|
|
if(triple->object_type == RDF_TYPE_IRI)
|
|
{
|
|
if((triple->object[0] == '_') && (triple->object[1] == ':'))
|
|
{
|
|
printf(" %s", triple->object);
|
|
}
|
|
else
|
|
{
|
|
printf(" <%s>", triple->object);
|
|
}
|
|
}
|
|
else if(triple->object_type == RDF_TYPE_PLAIN_LITERAL)
|
|
{
|
|
printf(" \"%s\"", triple->object);
|
|
if(triple->language != NULL)
|
|
{
|
|
printf("@%s", triple->language);
|
|
}
|
|
}
|
|
else if(triple->object_type == RDF_TYPE_XML_LITERAL)
|
|
{
|
|
printf(" \"%s\"^^rdf:XMLLiteral", triple->object);
|
|
}
|
|
else if(triple->object_type == RDF_TYPE_TYPED_LITERAL)
|
|
{
|
|
if((triple->datatype != NULL) && (triple->language != NULL))
|
|
{
|
|
printf(" \"%s\"@%s^^%s",
|
|
triple->object, triple->language, triple->datatype);
|
|
}
|
|
else if(triple->datatype != NULL)
|
|
{
|
|
printf(" \"%s\"^^%s", triple->object, triple->datatype);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf(" <%s> <---- UNKNOWN OBJECT TYPE", triple->object);
|
|
}
|
|
|
|
printf(" .\n");
|
|
}
|
|
else
|
|
{
|
|
printf(" INCOMPLETE .");
|
|
}
|
|
}
|
|
}
|
|
|
|
void rdfa_free_triple(rdftriple* triple)
|
|
{
|
|
free(triple->subject);
|
|
free(triple->predicate);
|
|
free(triple->object);
|
|
free(triple->datatype);
|
|
free(triple->language);
|
|
free(triple);
|
|
}
|
|
|
|
#ifndef LIBRDFA_IN_RAPTOR
|
|
/**
|
|
* Generates a namespace prefix triple for any application that is
|
|
* interested in processing namespace changes.
|
|
*
|
|
* @param context the RDFa context.
|
|
* @param prefix the name of the prefix
|
|
* @param IRI the fully qualified IRI that the prefix maps to.
|
|
*/
|
|
void rdfa_generate_namespace_triple(
|
|
rdfacontext* context, const char* prefix, const char* iri)
|
|
{
|
|
rdftriple* triple =
|
|
rdfa_create_triple(
|
|
"@prefix", prefix, iri, RDF_TYPE_NAMESPACE_PREFIX, NULL, NULL);
|
|
context->triple_callback(triple, context->callback_data);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Completes all incomplete triples that are part of the current
|
|
* context by matching the new_subject with the list of incomplete
|
|
* triple predicates.
|
|
*
|
|
* @param context the RDFa context.
|
|
*/
|
|
void rdfa_complete_incomplete_triples(rdfacontext* context)
|
|
{
|
|
// 10. If the [ skip element ] flag is 'false', and [ new subject ]
|
|
// was set to a non-null value, then any [ incomplete triple ]s
|
|
// within the current context should be completed:
|
|
//
|
|
// The [ list of incomplete triples ] from the current [ evaluation
|
|
// context ] ( not the [ local list of incomplete triples ]) will
|
|
// contain zero or more predicate URIs. This list is iterated, and
|
|
// each of the predicates is used with [ parent subject ] and
|
|
// [ new subject ] to generate a triple. Note that at each level
|
|
// there are two , lists of [ incomplete triple ]s; one for the
|
|
// current processing level (which is passed to each child element
|
|
// in the previous step), and one that was received as part of the
|
|
// [ evaluation context ]. It is the latter that is used in
|
|
// processing during this step.
|
|
unsigned int i;
|
|
for(i = 0; i < context->incomplete_triples->num_items; i++)
|
|
{
|
|
rdfalist* incomplete_triples = context->incomplete_triples;
|
|
rdfalistitem* incomplete_triple = incomplete_triples->items[i];
|
|
|
|
if(incomplete_triple->flags & RDFALIST_FLAG_FORWARD)
|
|
{
|
|
// If [direction] is 'forward' then the following triple is generated:
|
|
//
|
|
// subject
|
|
// [parent subject]
|
|
// predicate
|
|
// the predicate from the iterated incomplete triple
|
|
// object
|
|
// [new subject]
|
|
rdftriple* triple =
|
|
rdfa_create_triple(context->parent_subject,
|
|
(const char*)incomplete_triple->data, context->new_subject, RDF_TYPE_IRI,
|
|
NULL, NULL);
|
|
context->triple_callback(triple, context->callback_data);
|
|
}
|
|
else
|
|
{
|
|
// If [direction] is not 'forward' then this is the triple generated:
|
|
//
|
|
// subject
|
|
// [new subject]
|
|
// predicate
|
|
// the predicate from the iterated incomplete triple
|
|
// object
|
|
// [parent subject]
|
|
rdftriple* triple =
|
|
rdfa_create_triple(context->new_subject,
|
|
(const char*)incomplete_triple->data, context->parent_subject, RDF_TYPE_IRI,
|
|
NULL, NULL);
|
|
context->triple_callback(triple, context->callback_data);
|
|
}
|
|
free(incomplete_triple);
|
|
}
|
|
context->incomplete_triples->num_items = 0;
|
|
}
|
|
|
|
void rdfa_complete_type_triples(
|
|
rdfacontext* context, const rdfalist* type_of)
|
|
{
|
|
// 6.1 One or more 'types' for the [new subject] can be set by
|
|
// using @type_of. If present, the attribute must contain one or
|
|
// more URIs, obtained according to the section on URI and CURIE
|
|
// Processing, each of which is used to generate a triple as follows:
|
|
//
|
|
// subject
|
|
// [new subject]
|
|
// predicate
|
|
// http://www.w3.org/1999/02/22-rdf-syntax-ns#type
|
|
// object
|
|
// full URI of 'type'
|
|
unsigned int i;
|
|
|
|
rdfalistitem** iptr = type_of->items;
|
|
for(i = 0; i < type_of->num_items; i++)
|
|
{
|
|
rdfalistitem* curie = *iptr;
|
|
|
|
rdftriple* triple = rdfa_create_triple(context->new_subject,
|
|
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
|
(const char*)curie->data, RDF_TYPE_IRI, NULL, NULL);
|
|
|
|
context->triple_callback(triple, context->callback_data);
|
|
iptr++;
|
|
}
|
|
}
|
|
|
|
void rdfa_complete_relrev_triples(
|
|
rdfacontext* context, const rdfalist* rel, const rdfalist* rev)
|
|
{
|
|
// 7. If in any of the previous steps a [current object resource]
|
|
// was set to a non-null value, it is now used to generate triples
|
|
unsigned int i;
|
|
|
|
// Predicates for the [current object resource] can be set by using
|
|
// one or both of the @rel and @rev attributes.
|
|
|
|
// If present, @rel will contain one or more URIs, obtained
|
|
// according to the section on CURIE and URI Processing each of
|
|
// which is used to generate a triple as follows:
|
|
//
|
|
// subject
|
|
// [new subject]
|
|
// predicate
|
|
// full URI
|
|
// object
|
|
// [current object resource]
|
|
if(rel != NULL)
|
|
{
|
|
rdfalistitem** relptr = rel->items;
|
|
for(i = 0; i < rel->num_items; i++)
|
|
{
|
|
rdfalistitem* curie = *relptr;
|
|
|
|
rdftriple* triple = rdfa_create_triple(context->new_subject,
|
|
(const char*)curie->data, context->current_object_resource, RDF_TYPE_IRI,
|
|
NULL, NULL);
|
|
|
|
context->triple_callback(triple, context->callback_data);
|
|
relptr++;
|
|
}
|
|
}
|
|
|
|
// If present, @rev will contain one or more URIs, obtained
|
|
// according to the section on CURIE and URI Processing each of which
|
|
// is used to generate a triple as follows:
|
|
//
|
|
// subject
|
|
// [current object resource]
|
|
// predicate
|
|
// full URI
|
|
// object
|
|
// [new subject]
|
|
if(rev != NULL)
|
|
{
|
|
rdfalistitem** revptr = rev->items;
|
|
for(i = 0; i < rev->num_items; i++)
|
|
{
|
|
rdfalistitem* curie = *revptr;
|
|
|
|
rdftriple* triple = rdfa_create_triple(
|
|
context->current_object_resource, (const char*)curie->data,
|
|
context->new_subject, RDF_TYPE_IRI, NULL, NULL);
|
|
|
|
context->triple_callback(triple, context->callback_data);
|
|
revptr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void rdfa_save_incomplete_triples(
|
|
rdfacontext* context, const rdfalist* rel, const rdfalist* rev)
|
|
{
|
|
unsigned int i;
|
|
// 8. If however [current object resource] was set to null, but
|
|
// there are predicates present, then they must be stored as
|
|
// [incomplete triple]s, pending the discovery of a subject that
|
|
// can be used as the object. Also, [current object resource]
|
|
// should be set to a newly created [bnode]
|
|
context->current_object_resource = rdfa_create_bnode(context);
|
|
|
|
// If present, @rel must contain one or more URIs, obtained
|
|
// according to the section on CURIE and URI Processing each of
|
|
// which is added to the [local local list of incomplete triples]
|
|
// as follows:
|
|
//
|
|
// predicate
|
|
// full URI
|
|
// direction
|
|
// forward
|
|
if(rel != NULL)
|
|
{
|
|
rdfalistitem** relptr = rel->items;
|
|
for(i = 0; i < rel->num_items; i++)
|
|
{
|
|
rdfalistitem* curie = *relptr;
|
|
|
|
rdfa_add_item(
|
|
context->local_incomplete_triples, curie->data,
|
|
(liflag_t)(RDFALIST_FLAG_FORWARD | RDFALIST_FLAG_TEXT));
|
|
|
|
relptr++;
|
|
}
|
|
}
|
|
|
|
// If present, @rev must contain one or more URIs, obtained
|
|
// according to the section on CURIE and URI Processing, each of
|
|
// which is added to the [local list of incomplete triples] as follows:
|
|
//
|
|
// predicate
|
|
// full URI
|
|
// direction
|
|
// reverse
|
|
if(rev != NULL)
|
|
{
|
|
rdfalistitem** revptr = rev->items;
|
|
for(i = 0; i < rev->num_items; i++)
|
|
{
|
|
rdfalistitem* curie = *revptr;
|
|
|
|
rdfa_add_item(
|
|
context->local_incomplete_triples, curie->data,
|
|
(liflag_t)(RDFALIST_FLAG_REVERSE | RDFALIST_FLAG_TEXT));
|
|
|
|
revptr++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void rdfa_complete_object_literal_triples(rdfacontext* context)
|
|
{
|
|
// 9. The next step of the iteration is to establish any
|
|
// [current object literal];
|
|
//
|
|
// Predicates for the [current object literal] can be set by using
|
|
// @property. If present, a URI is obtained according to the
|
|
// section on CURIE and URI Processing, and then the actual literal
|
|
// value is obtained as follows:
|
|
char* current_object_literal = NULL;
|
|
rdfresource_t type = RDF_TYPE_UNKNOWN;
|
|
|
|
unsigned int i;
|
|
rdfalistitem** pptr;
|
|
|
|
// * as a [plain literal] if:
|
|
// o @content is present;
|
|
// o or all children of the [current element] are text nodes;
|
|
// o or there are no child nodes; TODO: Is this needed?
|
|
// o or the body of the [current element] does have non-text
|
|
// child nodes but @datatype is present, with an empty value.
|
|
//
|
|
// Additionally, if there is a value for [current language] then
|
|
// the value of the [plain literal] should include this language
|
|
// information, as described in [RDF-CONCEPTS]. The actual literal
|
|
// is either the value of @content (if present) or a string created
|
|
// by concatenating the text content of each of the descendant
|
|
// elements of the [current element] in document order.
|
|
if((context->content != NULL))
|
|
{
|
|
current_object_literal = context->content;
|
|
type = RDF_TYPE_PLAIN_LITERAL;
|
|
}
|
|
else if(index(context->xml_literal, '<') == NULL)
|
|
{
|
|
current_object_literal = context->plain_literal;
|
|
type = RDF_TYPE_PLAIN_LITERAL;
|
|
}
|
|
else if(strlen(context->plain_literal) == 0)
|
|
{
|
|
current_object_literal = (char*)"";
|
|
type = RDF_TYPE_PLAIN_LITERAL;
|
|
}
|
|
else if((context->xml_literal != NULL) &&
|
|
(context->datatype != NULL) &&
|
|
(strlen(context->xml_literal) > 0) &&
|
|
(strcmp(context->datatype, "") == 0))
|
|
{
|
|
current_object_literal = context->xml_literal;
|
|
type = RDF_TYPE_PLAIN_LITERAL;
|
|
}
|
|
|
|
|
|
// * as an [XML literal] if:
|
|
// o the [current element] has any child nodes that are not
|
|
// simply text nodes, and @datatype is not present, or is
|
|
// present, but is set to rdf:XMLLiteral.
|
|
//
|
|
// The value of the [XML literal] is a string created by
|
|
// serializing to text, all nodes that are descendants of the
|
|
// [current element], i.e., not including the element itself, and
|
|
// giving it a datatype of rdf:XMLLiteral.
|
|
if((current_object_literal == NULL) &&
|
|
(index(context->xml_literal, '<') != NULL) &&
|
|
((context->datatype == NULL) ||
|
|
(strcmp(context->datatype,
|
|
"http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral") == 0)))
|
|
{
|
|
current_object_literal = context->xml_literal;
|
|
type = RDF_TYPE_XML_LITERAL;
|
|
}
|
|
|
|
// * as a [typed literal] if:
|
|
// o @datatype is present, and does not have an empty
|
|
// value.
|
|
//
|
|
// The actual literal is either the value of @content (if present)
|
|
// or a string created by concatenating the value of all descendant
|
|
// text nodes, of the [current element] in turn. The final string
|
|
// includes the datatype URI, as described in [RDF-CONCEPTS], which
|
|
// will have been obtained according to the section on CURIE and
|
|
// URI Processing.
|
|
if((context->datatype != NULL) && (strlen(context->datatype) > 0))
|
|
{
|
|
if(context->content != NULL)
|
|
{
|
|
current_object_literal = context->content;
|
|
type = RDF_TYPE_TYPED_LITERAL;
|
|
}
|
|
else if(strcmp(context->datatype,
|
|
"http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral") != 0)
|
|
{
|
|
current_object_literal = context->plain_literal;
|
|
type = RDF_TYPE_TYPED_LITERAL;
|
|
}
|
|
}
|
|
|
|
// TODO: Setting the current object literal to the plain literal in
|
|
// the case of xsd:string isn't mentioned in the syntax
|
|
// processing document.
|
|
if((current_object_literal == NULL) && (context->datatype != NULL) &&
|
|
(strcmp(
|
|
context->datatype, "http://www.w3.org/2001/XMLSchema#string") == 0))
|
|
{
|
|
current_object_literal = context->plain_literal;
|
|
type = RDF_TYPE_TYPED_LITERAL;
|
|
}
|
|
|
|
// The [current object literal] is then used with each predicate to
|
|
// generate a triple as follows:
|
|
//
|
|
// subject
|
|
// [new subject]
|
|
// predicate
|
|
// full URI
|
|
// object
|
|
// [current object literal]
|
|
pptr = context->property->items;
|
|
for(i = 0; i < context->property->num_items; i++)
|
|
{
|
|
|
|
rdfalistitem* curie = *pptr;
|
|
rdftriple* triple = NULL;
|
|
|
|
triple = rdfa_create_triple(context->new_subject,
|
|
(const char*)curie->data, current_object_literal, type, context->datatype,
|
|
context->language);
|
|
|
|
context->triple_callback(triple, context->callback_data);
|
|
pptr++;
|
|
}
|
|
|
|
// TODO: Implement recurse flag being set to false
|
|
//
|
|
// Once the triple has been created, if the [datatype] of the
|
|
// [current object literal] is rdf:XMLLiteral, then the [recurse]
|
|
// flag is set to false
|
|
context->recurse = 0;
|
|
}
|