1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-04 17:49:45 +02:00
2010-01-24 09:19:39 +00:00

522 lines
15 KiB
C

/*
* rdf-tree.c - Retrieve statements from persistent Redland storage.
*
* Copyright (C) 2003-2004 Morten Frederiksen - http://purl.org/net/morten/
*
* and
*
* Copyright (C) 2000-2006, David Beckett http://purl.org/net/dajobe/
* Copyright (C) 2000-2004, 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.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <redland.h>
#include <openssl/lhash.h>
const char *VERSION = "0.4";
struct options {
librdf_node *context;
char *database;
char *directory;
char *host;
char *model;
int level;
int port;
char *output;
char *password;
int quiet;
char *user;
} opts;
int main(int argc, char *argv[]);
int tree(librdf_world * world, librdf_node * node, librdf_model * model,
librdf_model * outputmodel, LHASH * table, int level);
void hash_free(void *data);
int getoptions(int argc, char *argv[], librdf_world * world);
int usage(char *argv0, int version);
int
main(int argc, char *argv[])
{
/* Redland objects. */
librdf_world *world;
librdf_storage *storage;
librdf_model *model;
librdf_uri *uri = 0;
librdf_storage *outputstorage;
librdf_model *outputmodel;
librdf_storage *contextstorage;
librdf_model *contextmodel;
librdf_stream *stream;
librdf_serializer *serializer;
int argnum;
char *storage_type;
char *storage_options;
/* Create rdflib world. */
world = librdf_new_world();
if(!world) {
fprintf(stderr, "%s: Failed to create Redland world\n", argv[0]);
return (1);
};
librdf_world_open(world);
/* Parse command line options (if possible). */
argnum = getoptions(argc, argv, world);
/* Check for URI argument. */
if(argnum < argc) {
uri = librdf_new_uri(world, argv[argnum]);
if(!uri) {
fprintf(stderr, "%s: Failed to create input uri\n", argv[0]);
exit(1);
};
};
/* Set storage options. */
if(opts.database) {
storage_type = strdup("mysql");
storage_options =
malloc(strlen(opts.host) + strlen(opts.database) + strlen(opts.user) +
strlen(opts.password) + 120);
if(!storage_type || !storage_options) {
fprintf(stderr, "%s: Failed to create 'mysql' storage options\n",
argv[0]);
return (1);
};
sprintf(storage_options,
"host='%s',database='%s',port='%i',user='%s',password='%s',contexts='yes',write='no'",
opts.host, opts.database, opts.port, opts.user, opts.password);
}
else {
storage_type = strdup("hashes");
storage_options = malloc(strlen(opts.directory) + 120);
if(!storage_type || !storage_options) {
fprintf(stderr, "%s: Failed to create 'hashes' storage options\n",
argv[0]);
return (1);
};
sprintf(storage_options,
"hash-type='bdb',dir='%s',contexts='yes',write='no'",
opts.directory);
};
/* Create storage. */
storage =
librdf_new_storage(world, storage_type, opts.model, storage_options);
if(!storage) {
fprintf(stderr, "%s: Failed to create storage (%s/%s/%s)\n", argv[0],
storage_type, opts.model, storage_options);
return (1);
}
/* Create model. */
model = librdf_new_model(world, storage, NULL);
if(!model) {
fprintf(stderr, "%s: Failed to create model\n", argv[0]);
return (1);
}
/* Create output storage. */
outputstorage = librdf_new_storage(world, "memory", "output", "");
if(!outputstorage) {
fprintf(stderr, "%s: Failed to create output storage\n", argv[0]);
return (1);
}
/* Create output model. */
outputmodel = librdf_new_model(world, outputstorage, NULL);
if(!outputmodel) {
fprintf(stderr, "%s: Failed to create output model\n", argv[0]);
return (1);
}
/* Create serializer. */
serializer = librdf_new_serializer(world, opts.output, NULL, NULL);
if(!serializer) {
fprintf(stderr, "%s: Failed to create serializer\n", argv[0]);
return (1);
}
if(librdf_model_size(model) != -1 && !opts.quiet)
fprintf(stderr, "%s: Model '%s' contains %d statements.\n", argv[0],
opts.model, librdf_storage_size(storage));
/*
stream=librdf_model_as_stream(model);
while (!librdf_stream_end(stream))
{
librdf_statement *s;
librdf_node *n;
s=librdf_stream_get_object(stream);
fprintf(stderr,"%s\n",librdf_statement_to_string(s));
n=librdf_stream_get_context(stream);
fprintf(stderr,"- context: %s\n",n?librdf_node_to_string(n):"-");
librdf_stream_next(stream);
};
librdf_free_stream(stream);
*/
/* Only statements with given context? */
if(opts.context) {
if(!opts.quiet)
fprintf(stderr, "%s: Creating context storage...\n", argv[0]);
/* Create context storage. */
contextstorage = librdf_new_storage(world, "memory", "context", "");
if(!contextstorage) {
fprintf(stderr, "%s: Failed to create context storage\n", argv[0]);
return (1);
};
/* Create context model. */
contextmodel = librdf_new_model(world, contextstorage, NULL);
if(!contextmodel) {
fprintf(stderr, "%s: Failed to create context model\n", argv[0]);
return (1);
};
/* Extract statements with given context. */
if(!(stream = librdf_model_context_as_stream(model, opts.context))) {
fprintf(stderr, "%s: Failed to serialize context model\n", argv[0]);
return (1);
};
if(librdf_model_add_statements(contextmodel, stream)) {
fprintf(stderr, "%s: Failed to add statements to context model\n",
argv[0]);
return (1);
};
librdf_free_model(model);
librdf_free_storage(storage);
storage = contextstorage;
model = contextmodel;
};
/* Populate output model... */
if(uri) {
int rc = 0;
LHASH *table =
lh_new((LHASH_HASH_FN_TYPE) lh_strhash, (LHASH_COMP_FN_TYPE) strcmp);
if(!table) {
fprintf(stderr, "%s: Failed to create hash table\n", argv[0]);
return (1);
};
if(!opts.quiet)
fprintf(stderr, "%s: Populating output model from uri...\n", argv[0]);
/* Recursively extract statements about subject... */
rc =
tree(world, librdf_new_node_from_uri(world, uri), model, outputmodel,
table, opts.level);
lh_doall(table, (LHASH_DOALL_FN_TYPE) hash_free);
lh_free(table);
if(rc) {
fprintf(stderr, "%s: Failed to extract statements from model (%d)\n",
argv[0], rc);
return (1);
};
librdf_free_model(model);
librdf_free_storage(storage);
}
else {
if(!opts.quiet)
fprintf(stderr, "%s: Outputting entire model...\n", argv[0]);
/* No restraints, use entire model as output. */
librdf_free_model(outputmodel);
librdf_free_storage(outputstorage);
outputstorage = storage;
outputmodel = model;
};
/* Serialize output... */
if(!opts.quiet)
fprintf(stderr, "%s: Serializing...\n", argv[0]);
if(librdf_serializer_serialize_model(serializer, stdout, NULL, outputmodel)) {
fprintf(stderr, "%s: Failed to serialize output model\n", argv[0]);
return (1);
};
/* Clean up. */
librdf_free_serializer(serializer);
librdf_free_model(outputmodel);
librdf_free_storage(outputstorage);
librdf_free_world(world);
/* keep gcc -Wall happy */
return (0);
}
int
tree(librdf_world * world, librdf_node * node, librdf_model * model,
librdf_model * outputmodel, LHASH * table, int level)
{
librdf_stream *instream;
librdf_node *object;
librdf_statement *statement;
int rc;
librdf_node_type ont;
librdf_node *rdftype =
librdf_new_node_from_uri_string(world,
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
/* Add node to hash, to prevent cycles. */
lh_insert(table, strdup(librdf_node_to_string(node)));
if(lh_error(table)) {
return 1;
}
/* Find all statements about node. */
if(!
(statement =
librdf_new_statement_from_nodes(world, librdf_new_node_from_node(node),
NULL, NULL))) {
return 2;
}
if(!(instream = librdf_model_find_statements(model, statement))) {
return 0;
}
while(!librdf_stream_end(instream)) {
/* Add statement to output model. */
statement = librdf_stream_get_object(instream);
if(librdf_model_add_statement(outputmodel,
librdf_new_statement_from_statement
(statement)))
return 4;
/* Recurse? */
if(level && !librdf_node_equals(rdftype,
librdf_statement_get_predicate
(statement))) {
object = librdf_statement_get_object(statement);
ont = librdf_node_get_type(object);
if(ont == LIBRDF_NODE_TYPE_RESOURCE || ont == LIBRDF_NODE_TYPE_BLANK) {
/*
librdf_statement_print(statement,stderr);
fprintf(stderr,"%s","\n");
*/
/* Don't recurse if object is known... */
if(!lh_retrieve(table, librdf_node_to_string(object))) {
rc = tree(world, object, model, outputmodel, table, level - 1);
if(rc)
return rc;
}
};
};
librdf_stream_next(instream);
};
librdf_free_stream(instream);
return 0;
};
void
hash_free(void *data)
{
free(data);
};
int
getoptions(int argc, char *argv[], librdf_world * world)
{
/* Define command line options. */
struct option opts_long[] = {
{"help", no_argument, NULL, '?'},
{"context", required_argument, NULL, 'c'},
{"database", required_argument, NULL, 's'},
{"directory", required_argument, NULL, 'd'},
{"host", required_argument, NULL, 'h'},
{"level", required_argument, NULL, 'l'},
{"model", required_argument, NULL, 'm'},
{"output", required_argument, NULL, 'o'},
{"port", required_argument, NULL, 'P'},
{"password", optional_argument, NULL, 'p'},
{"quiet", no_argument, NULL, 'q'},
{"user", required_argument, NULL, 'u'},
{"version", no_argument, NULL, 'v'},
{0, 0, 0, 0}
};
const char *opts_short = "?c:D:d:h:l:m:o:P:p:qu:v";
int i = 1;
char c;
char *buffer;
int ttypasswd = 1;
/* Set defaults. */
opts.context = 0;
opts.level = 1;
opts.password = 0;
opts.port = 3306;
opts.quiet = 0;
opts.user = 0;
if(!(opts.directory = strdup("./"))
|| !(opts.host = strdup("mysql"))
|| !(opts.model = strdup("redland"))
|| !(opts.output = strdup("rdfxml"))
|| !(opts.database = strdup("redland"))) {
fprintf(stderr, "%s: Failed to allocate default options\n", argv[0]);
exit(1);
};
while((c = getopt_long(argc, argv, opts_short, opts_long, &i)) != -1) {
if(optarg) {
buffer = malloc(strlen(optarg) + 1);
if(!buffer) {
fprintf(stderr,
"%s: Failed to allocate buffer for command line argument (%s)\n",
argv[0], optarg);
exit(1);
};
strncpy(buffer, optarg, strlen(optarg) + 1);
};
switch (c) {
case '?':
usage(argv[0], 0);
case 'c':
free(buffer);
opts.context = librdf_new_node_from_uri_string(world, optarg);
if(!opts.context) {
fprintf(stderr, "%s: Failed to create context node (%s)\n", argv[0],
optarg);
exit(1);
};
break;
case 'D':
free(opts.directory);
opts.directory = 0;
opts.database = buffer;
break;
case 'd':
free(opts.database);
opts.database = 0;
opts.directory = buffer;
break;
case 'h':
opts.host = buffer;
break;
case 'l':
free(buffer);
opts.level = atoi(optarg);
break;
case 'm':
opts.model = buffer;
break;
case 'o':
free(opts.output);
opts.output = buffer;
break;
case 'P':
free(buffer);
opts.port = atoi(optarg);
break;
case 'p':
opts.password = buffer;
ttypasswd = 0;
break;
case 'q':
opts.quiet = 1;
break;
case 'u':
opts.user = buffer;
break;
case 'v':
usage(argv[0], 1);
default:
fprintf(stderr, "%s: Invalid option (%c)\n", argv[0], c);
usage(argv[0], 0);
}
}
/* Flag missing user name. */
if(opts.database && !opts.user) {
fprintf(stderr, "%s: Missing user name for mysql storage\n", argv[0]);
usage(argv[0], 0);
exit(1);
};
/* Read password from tty if not specified. */
if(opts.database && ttypasswd) {
char c2;
int i2 = 0;
opts.password = malloc(128);
if(!opts.password) {
fprintf(stderr, "%s: Failed to allocate buffer for password\n",
argv[0]);
exit(1);
};
fprintf(stderr, "%s: Enter password for %s@%s/%s: ", argv[0], opts.user,
opts.host, opts.database);
while((c2 = getchar()) != '\n') {
opts.password[i2++] = c2;
if(i2 == 127)
break;
};
opts.password[i2++] = 0;
};
return optind;
}
int
usage(char *argv0, int version)
{
printf("\n\
%s Version %s\n\
Retrieve statements from persistent Redland storage.\n\
* Copyright (C) 2003 Morten Frederiksen - http://purl.org/net/morten/\n\
* Copyright (C) 2000-2003 David Beckett - http://purl.org/net/dajobe/\n\
", argv0, VERSION);
if(version)
exit(0);
printf("\n\
usage: %s [options] [ <URI> ]\n\
\n\
-?, --help Display this help message and exit.\n\
-c<uri>, --context=<uri>\n\
Extract only statements with given context URI.\n\
-D<database>, --database=<database>\n\
Name of MySQL database to use, default is 'redland'.\n\
-d<directory>, --directory=<directory>\n\
Directory to use for BDB files. When provided implies use\n\
of 'hashes' storage type instead of 'mysql'.\n\
-h<host name>, --host=<host name>\n\
Host to contact for MySQL connections, default is 'mysql'.\n\
-l<number>, --level=<number>\n\
The number of levels of statements to extract. Default is\n\
1, also returning statements about objects.\n\
-m<model id>, --model=<model id>\n\
Identifier for (name of) storage (model name for storage\n\
type 'mysql', base file name for storage type 'hashes'),\n\
default is 'redland'.\n\
-o<syntax id>, --output=<syntax id>\n\
Syntax identifier for serialization, 'ntriples' or\n\
'rdfxml' (default).\n\
-p<password>, --password=<password>\n\
Password to use when connecting to MySQL server.\n\
If password is not given it's asked from the tty.\n\
-P<port number>, --port=<port number>\n\
The port number to use when connecting to MySQL server.\n\
Default port number is 3306.\n\
-q, --quiet\n\
No informational messages, only errors.\n\
-u<user name>, --user=<user name>\n\
User name for MySQL server.\n\
-v, --version Output version information and exit.\n\
\n\
", argv0);
exit(1);
}