#!/usr/bin/perl

$REVISION = '$Id: algae,v 1.87 2004/08/06 11:18:14 eric Exp $ ';

use strict;

#BEGIN {unshift@INC,('../../..');}
package algaeScript;
use vars qw(%SerializerClassAbbreviations
	    $IFACE $IFACE_unknown $IFACE_Gnu $IFACE_Perl);

use Pod::Usage;
use W3C::Util::Scriptopt qw(:config guess_shell permute no_ignore_case bundling);
use W3C::Util::Exception qw(&throw &catch &DieHandler);
use W3C::Rdf::RdfApp;
use W3C::Rdf::Atoms qw($Value_NULL);

%SerializerClassAbbreviations = ('statements' => 'W3C::Rdf::StatementsSerializer', 
				 'RDFXML' => 'W3C::Rdf::XmlSerializer', 
				 'arrows' => 'W3C::Rdf::ArrowSerializer', 
				 'n3' => 'W3C::Rdf::N3Serializer', 
				 'ntriples' => 'W3C::Rdf::NTriplesSerializer', 
				 'dot' => 'W3C::Rdf::DotSerializer'
				 );

($IFACE_unknown, $IFACE_Gnu, $IFACE_Perl) = (0..2);
$IFACE = $IFACE_unknown;

eval {
    local($SIG{"__DIE__"}) = \&DieHandler;
    my $context = new W3C::Rdf::RdfApp(-forceHost => undef, 
				       -forceDir => undef);
    new algaeScript($context)->execute();
}; if ($@) {if (my $ex = &catch('W3C::Util::Exception')) {
	die $ex->toString();
    } else {
	die $@;
    }
}

sub new {
    my ($proto, $context) = @_;
    my $class = ref($proto) || $proto;
    my $self = {};
    bless ($self, $class);
    my $queryHandler = $context->getQueryHandler($self, {-uniqueResults => 1});
    $self->{-queryHandler} = $queryHandler;
    $self->{-context} = $context;
    $self->{LOCATION_STACK} = [];
    $self->{-atomDictionary} = $context->{-atomDictionary}; # for convenience
    return $self;
}

sub execute {
    my ($self) = @_;

    my $queryLangNames = {'Algae' => $QL_ALGAE, 
			  'RDQL' => $QL_RDQL, 
			  'BRQL' => $QL_BRQL, 
			  'SeRQL' => $QL_SeRQL};
    my $queryLang = $QL_ALGAE;

    my $inputLangNames = {'RDFXML' => undef, 
			  'n3' => undef};
    my $inputLang = 'RDFXML';
    my $debugOutput = undef;

    *DBG = *STDOUT;
    my ($help, $man);
    my ($reportStream, $reportParms, $outputFile);
    $reportParms = [];
    my $argsProcessed = 0;
    &W3C::Util::Scriptopt::setLocationHandler($self);
    my $res = &GetOptionsScript(
	'algae' => undef, 
	'lang|l=s' => sub {
	    local($SIG{"__DIE__"}) = \&DieHandler;
	    my (undef, $val) = @_;
	    if (exists $queryLangNames->{$val}) {
		$queryLang = $queryLangNames->{$val};
	    } else {
		my $langs = join(', ', keys %$queryLangNames);
		&throw(new W3C::Util::Exception(
		-message => 
		"\"$val\" not supported. Use one of $langs."));
	    }
	}, 
	'input|i=s' => sub {
	    local($SIG{"__DIE__"}) = \&DieHandler;
	    my (undef, $val) = @_;
	    if (exists $inputLangNames->{$val}) {
		$inputLang = $val;
	    } else {
		my $langs = join(', ', keys %$inputLangNames);
		&throw(new W3C::Util::Exception(
		-message => 
		"\"$val\" not supported. Use one of $langs."));
	    }
	}, 
	'sClass=s' => \$reportStream, # deprecated
	'sParm=s@' => $reportParms, # deprecated
	'forceHost=s' => \$self->{-context}{-forceHost}, 
	'forcePath=s' => \$self->{-context}{-forcePath}, 
	'reportClass=s' => \$reportStream, 
	'reportParm=s@' => $reportParms, 
	'o=s' => \$outputFile, 
	'read|d=s' => sub {
	    local($SIG{"__DIE__"}) = \&DieHandler;
	    my $inputSource = &W3C::Rdf::RdfApp::getInputSource($_[1]);
	    $self->{-context}->parse($inputSource->getByteStream(), 
				     $inputSource->getPublicId(), 
				     $inputLang, $self->{-queryHandler});
	}, 
	'q' => sub {
	    local($SIG{"__DIE__"}) = \&DieHandler;
	    $self->interactiveQueryBuilder();
	    ++$argsProcessed;
	}, 
	'help|?' => \$help, 
	'man' => \$man, 
	'query|f=s' => sub {
	    local($SIG{"__DIE__"}) = \&DieHandler;
	    my $queryFile = $_[1];
	    open (QF, $queryFile) || 
		&throw(new W3C::Util::FileOperationException(-filename => $queryFile,
							     -operation => 'read'));
	    local $/ = undef;
	    my $q = <QF>;
	    close QF;
	    $self->_executeQuery($queryLang, $q, $reportStream, $reportParms, $outputFile);
	    ++$argsProcessed;
	}, 
	't=s' => sub {
	    local($SIG{"__DIE__"}) = \&DieHandler;
	    if ($debugOutput) {
		close (DBG);
	    }
	    *DBG = undef;
	    $debugOutput = $_[1];
	    open (DBG, ">$debugOutput") || 
		&throw(new W3C::Util::FileOperationException(-filename => $debugOutput,
							     -operation => 'read'));
	    $main::DBG = \*DBG;
	}, 
	'<>' => sub {
	    local($SIG{"__DIE__"}) = \&DieHandler;
	    $self->_executeQuery($queryLang, $_[0], $reportStream, $reportParms, $outputFile);
	    ++$argsProcessed;
	}, 
    );
    &pod2usage(-exitstatus => 0, -verbose => 1) if $help;
    &pod2usage(-exitstatus => 0, -verbose => 2) if $man;
    &pod2usage(-exitstatus => 1, -verbose => 1, 
	       -message => "No queries processed.") if ($argsProcessed == 0);
}

# callback from Scriptopt
sub pushLocation {
    my ($self, $location) = @_;
    push (@{$self->{LOCATION_STACK}}, $location);
    $self->_setAttribution($location);
}

sub popLocation {
    my ($self, $location) = @_;
    if ($self->{LOCATION_STACK}[-1] ne $location) {
	&throw();
    }
    pop (@{$self->{LOCATION_STACK}});
    my $location = @{$self->{LOCATION_STACK}} ? $self->{LOCATION_STACK}[-1] : undef;
    $self->_setAttribution($location);
}

sub _setAttribution {
    my ($self, $uri) = @_;
    my $attrib = $uri ? $self->{-context}->makeInputAttribution($uri) : undef;
    $self->{-queryHandler}->setSourceAttribution($attrib);
}

sub _executeQuery {
    my ($self, $queryLang, $query, $reportStream, $reportParms, $outputFile) = @_;

    # Provide a data: attribution if we are reading things off the
    # command line.
    if (!@{$self->{LOCATION_STACK}}) {
	# Lightening up on requires so copping this from CGI::Util
	my $queryStr = $query;
	$queryStr=~s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
	# Was:
	# use CGI::Util qw(unescape escape);
	# my $queryStr = &escape($query);
	$self->_setAttribution("data:$queryStr");
    }

    # Set up reporter (output) stream.
    my $reporter = $self->makeReportStream($reportStream, $reportParms);
    if ($outputFile) {
	open (STDOUT, ">$outputFile") || 
	    &throw(new W3C::Util::FileOperationException(
							 -filename => $outputFile,
							 -operation => 'write'));
    }
    eval {
	my $queryHandler = $self->{-queryHandler};
	$query =~ s/^\#[^\n]*//;
	my $baseUri = $self->{LOCATION_STACK}[-1];
	my ($nodes, $selects, $messages, $proofs) = $queryHandler->interpret($query, $baseUri, $queryLang, 0x00);

	if ($queryHandler->{-templateDB}) {
	    print join ("\n", map {$_->toString} $queryHandler->{-templateDB}->getTriples()),"\n";
	    exit (0);
	}
	my $outUri = $self->{-atomDictionary}->getUri("pipe://stdout/", undef);
	my $outAttribution = $self->{-atomDictionary}->getGroundFactAttribution($outUri, undef, undef, undef);
	# print $outHandle $self->showQueryResults($nodes, $proofs, $outAttribution, $selects);
	if (@$nodes && @{$nodes->[0]}) {
	    print $self->showQueryResults($reporter, $nodes, $proofs, $outAttribution, $selects);
	}
    }; if ($@) {
	unlink $outputFile;
	if (my $ex = &catch('W3C::Util::Exception')) {
	    &throw($ex);
	} else {
	    &throw(new W3C::Util::PerlException());
	}
    }
}

# ./algae -d"\"W3C::Rdf::SqlDB\" (\"name:local:/db\" \"\"properties:rdf.prop)" -i

sub interactiveQueryBuilder {
    my ($self) = @_;
    eval {require Term::ReadLine;}; if ($@) {&throw()}
    my $term = new Term::ReadLine 'Query Builder';
    my $attribs = $term->Attribs;

    # Setup terminal and readline.
    my $origAttribs = {};
    my $SET1 = '"\'`('; # '"\'`<>!(';
    my $overrideAttribs = {'basic_word_break_characters' => $SET1, 
			   'completer_word_break_characters' => $SET1};
    foreach my $attrib (keys %$overrideAttribs) {
	$origAttribs->{$attrib} = $attribs->{$attrib};
	$attribs->{$attrib} = $overrideAttribs->{$attrib};
    }
    $term->ornaments('md,me,,');	# bold face prompt

    my $prompt = "command: ";

    # Some diagnostics to improve life for the user of the default perl inst.
    eval {require Term::ReadLine::Gnu}; if (!$@) {$IFACE = $IFACE_Gnu;}
    else {
	eval {require Term::ReadLine::Perl}; if (!$@) {$IFACE = $IFACE_Perl}
    }
    print DBG $IFACE == $IFACE_Gnu ? "Using GNU readline interface.\n" :
	$IFACE == $IFACE_Perl ? "Using perl readline interface.\n" :
	"Using unknown readline interface.\nYou may need Term::ReadLine::Gnu or Term::ReadLine::Perl.\n";

    my $preput = '';
    my $p = new W3C::Rdf::RLAlgaeParser('asdfasdf', $self->{-queryHandler}, 'unix://localhost/stdin');
    while (defined ($_ = $term->readline($prompt, $preput)) ) {
	my $res = eval {
	    my $query = $_;
	    if ($query =~ m/^ *(quit|exit|bye) *$/) {goto quitWithCommand}
	    my $actions = $p->parse(0x00);
	}, "\n";
	if ($@) {
	    if (my $ex = &catch('W3C::Util::Exception')) {
		warn $ex->toString;
	    } else {
		warn $@;
	    }
	};
	$term->addhistory($_) if /\S/;
    }
    print DBG "<EOF>\n";
  quitWithCommand:
    foreach my $attrib (keys %$origAttribs) {
	$attribs->{$attrib} = $origAttribs->{$attrib};
    }
}

sub _hairyCompletionFunction {
    my ($self, $term, $pCounter, $text, $line, $start, $end) = @_;
    print "_hairyCompletionFunction($term, $pCounter, $text, $line, $start, $end)\n";
    my $attribs = $term->Attribs;

    if ($line =~ /^\s*\(/ && 1) {
	my ($tree, $delim, $newSymbs, $variableSet) = (undef, undef, undef, {});
	my $algae = substr($line, 0, $start);
	eval {
	    ($tree, $delim, $newSymbs) = 
		new W3C::Util::SExpr()->parse(\$algae, undef, 
					      {-noTokensAtRoot => 1, 
					       -noNonTermException => 1, 
					       -laterSymbols => $variableSet});
	};
    }

    if (substr($line, 0, $start) =~ /^\s*$/) {
	$attribs->{completion_word} = ['quit', 'exit', 'bye', '('];
	undef $attribs->{completion_display_matches_hook};
	return $term->completion_matches($text,
					 $attribs->{'list_completion_function'});
    } elsif ($line =~ /^(\s*\(()\s*)(\w*)$/) {
	my $soFar = $1;
	my $len = length $soFar;
	my $cmds = ['ask', 'collect', 'namespace', 'attach'];
	my @list = grep {substr($_, 0, $len) eq $soFar} @$cmds;
	$attribs->{completion_word} = [@$cmds]; # @list];
	undef $attribs->{completion_display_matches_hook};
	return $term->completion_matches($text,
					 $attribs->{'list_completion_function'});
    } elsif ($line =~ /^(\s*\(()\s*)(\w*) +$/) {
	$attribs->{completion_word} = ['\'('];
	undef $attribs->{completion_display_matches_hook};
	return $term->completion_matches($text,
					 $attribs->{'list_completion_function'});
    } elsif ($line =~ /^(\s*\(()\s*)(\w*) *\'\( *([\w\:\/0-9\_\-]*)$/) {
#	$attribs->{completion_display_matches_hook} = sub {$self->db_display_match_list($term, @_)};
	return $term->completion_matches($text,
					 sub {$self->db_name_completion_function($term, $pCounter, ['('], @_)});
    } elsif ($line =~ /^(\s*\(()\s*)(\w*) *\'\( *([\w\:\/0-9\_\-]+) +$/) {
	$attribs->{completion_word} = ['('];
	undef $attribs->{completion_display_matches_hook};
	return $term->completion_matches($text,
					 $attribs->{'list_completion_function'});
    } else {			# put mput lcd
	undef $attribs->{completion_display_matches_hook};
	return ();		# local file name completion
    }
}

sub db_display_match_list {
    my ($self, $term, $matches, $num_matches, $max_length) = @_;
    #print "\n\nMATCH:{", &_ray($matches), ", $num_matches, $max_length\n\n";
#    map { $_ =~ s|.*/([^/])|\1|; }(@{$matches});
    $term->display_match_list($matches);
    $term->forced_update_display;
    #print " ==> $_}";
}

sub _ray {
    my ($array, @rest) = @_;
    if (ref $array eq 'ARRAY') {
	my $ret = join (' ', @$array);
	return "[$ret]";
    } else {
	my $ret = join (' ', $array, @rest);
	return "($ret)";
    }
}

sub db_name_completion_function ( $$ ) {
    my($self, $term, $pCounter, $suffix, $text, $state) = @_;
    my $attribs = $term->Attribs;
    my $entry;

    my @list = ($self->{-queryHandler}->getSourceNames(), @$suffix);
    #my @list = (qw(one two three), @$suffix);
    #print &_ray(@list), "\n";
    #print "\ndb_name_completion($text, $state)";
    #$self->dumpVars($term);
    if (!$state) {
	$$pCounter = 0;
	# $attribs->{completion_append_character} = ' ';
    } else {
	$$pCounter++;
    }
    my $ret = undef;
    for (; $$pCounter < @list; $$pCounter++) {
	if ($list[$$pCounter] =~ m/^$text/) {
	    $ret = $list[$$pCounter];
	    last;
	}
    }
    #print " ==> $ret\n";
    return $ret;
}

sub dumpVars {
    my ($self, $term) = @_;
    my $attribs = $term->Attribs;
    my @list = ('completion_query_items', 'basic_word_break_characters', 'basic_quote_characters', 'completer_word_break_characters', 'completer_quote_characters', 'filename_quote_characters', 'special_prefixes', 'completion_append_character', 'completion_suppress_append', 'completion_mark_symlink_dirs', 'ignore_completion_duplicates', 'filename_completion_desired', 'filename_quoting_desired', 'attempted_completion_over', 'completion_type', 'inhibit_completion');
    foreach my $attrib (@list) {
	print "$attrib: \"$attribs->{$attrib}\"\n";
    }
}

sub makeReportStream {
    my ($self, $reportStream, $reportParms) = @_;
    my $renderClass = $self->{ARGS}{-serializationClass};
    if (exists $SerializerClassAbbreviations{$reportStream}) {
	$reportStream = $SerializerClassAbbreviations{$reportStream};
    }

    $self->{ARGS}{-serializationParms} = {};
    foreach my $reportParm (@$reportParms) {
	if ($reportParm =~ m/([^= ]+) = (.*)/x) {
	    $self->{ARGS}{-serializationParms}->{$1} = $2;
	} else {
	    $self->{ARGS}{-serializationParms}->{$reportParm} = 1;
	}
    }

    my $ret = undef;
    if ($reportStream) {

	# @@@ duplicated
	my $sourceStr = "pipe://stdout/";
	my $outUri = $self->{-atomDictionary}->getUri($sourceStr, undef);
	my $outAttribution = $self->{-atomDictionary}->getGroundFactAttribution($outUri, undef, undef, undef);
	my $source = $outAttribution->getSource()->getUri();
	my $nsMap = {'r' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 
		     'attrib' => 'http://www.w3.org/2001/12/attributions/ns#'};

	# Put the flags together.
	my $flags = {-indent => 3, 
		     -publicId => $sourceStr, 
		     -systemId => $sourceStr, 
		     -noRdfTag => 0, 
		     -RdfDB => $self->{-context}->getRdfDB(), 
		     -allowAnonymousRefs => 1, 
		     -ignoreReifications => 1, 
		     -ignoreAnonymousReifications => 1, 
		     -neededNamespaces =>[keys %$nsMap],
		     -atomDictionary => $self->{-atomDictionary}, 
		     -resource => $outAttribution, 
		     -createNamespaces => 1, 
		     -importMap => $self->{-context}->getNamespaceHandler()};

	# Incorporate serialization parms.
	$flags = {%$flags, %{$self->{ARGS}{-serializationParms}}};
	# n3 could use -nestNonAnonNode => 0, 

	# Build the serializer class.
	$ret;
	eval "require $reportStream; \$ret = new $reportStream(\$flags);";
	if ($@) {&throw();}
    }
    return $ret;
}

sub showQueryResults {
    my ($self, $reporter, $nodes, $proofs, $outAttribution, $selects) = @_;
    my $source = $outAttribution->getSource()->getUri();
    my @ret;
    my $nsMap = {'r' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', 
		 'attrib' => 'http://www.w3.org/2001/12/attributions/ns#'};
    if ($reporter) {
	# @$proofs is an array of proofs.
	# Each proof is an array of statements.
	my $aggregateDB = new W3C::Rdf::RdfDB(-atomDictionary => $self->{-atomDictionary});
	foreach my $proof (@$proofs) {
	    $aggregateDB->copyTriples($proof);
	}
	my $statements = [$aggregateDB->getTriples];

	push (@ret, $self->showRdf($statements, $reporter, $source, $nsMap));
    } else {
	if ($self->{ARGS}{-serializationParms}{-barebones}) {
	    foreach my $row (@$nodes) {
		my @line;
		foreach my $col (@$row) {
		    $_ = $col;
		    &renderNode;
		    push (@line, $_);
		}
		push (@ret, join (',', @line));
	    }
	    push (@ret, undef); # newline at end
	} elsif ($self->{ARGS}{-serializationParms}{-resultSet}) {
	    push (@ret, $self->RSRenderer($nodes, $selects, $proofs));
	} else {
	    push (@ret, $self->arrayRenderer($nodes, $selects, $proofs, 
				  $self->{ARGS}{-serializationParms}{-proofs}));
	}
    }
    return join("\n", @ret);
}

sub renderNode {
    $_ = !defined $_ ? '!unbound!' : 
	$_ == $Value_NULL ? 'NULL' : 
	ref $_ eq 'ARRAY' ? $_ : 
	$_->isa('W3C::Rdf::Uri') ? '<'.$_->getUri.'>' : 
	$_->isa('W3C::Rdf::String') ? $_->getDatatype eq $main::XSD_INT ? $_->getString : '"'.$_->getString.'"' : 
	$_->isa('W3C::Rdf::BNode') ? '_:g'.$_->getId.'' : 
	$_->isa('W3C::Rdf::Attribution') ? '['.$_->getUri->getUri.']' : 
	&throw(new W3C::Util::Exception(-message => "don't know how to serialize \"$_\""));
}

sub arrayRenderer {
    my ($self, $rows, $selects, $proofs, $includeProofs) = @_;

    my %flags = (%{$self->{ARGS}{-serializationParms}});
    my $nsHandler = delete $flags{-ns} ? 
	new W3C::Util::NamespaceReducer(-relay => 
	    $self->{-context}->getNamespaceHandler()) : undef;
    if ($nsHandler) {
	$flags{-namespaceHandler} = $nsHandler;
    }

    my $tr;
    if ($self->{ARGS}{-serializationParms}{-xhtml}) {
	require W3C::XML::HTMLTableRenderer;
	$tr = new W3C::XML::HTMLTableRenderer();
    } else {
	require W3C::Util::TableRenderer;
	$tr = new W3C::Util::TableRenderer();
    }

    # Allocate an extra column for spillover in the proof strings.
    $tr->addHeaders($includeProofs ? [@$selects, ''] : $selects);

    # Walk through each row and optionally add the proofString after it.
    for (my $row = 0; $row < @$rows; $row++) {
	$tr->addData(map {$self->{-atomDictionary}->renderAtom($_, %flags)} @{$rows->[$row]});
	if ($includeProofs) {
	    my $proofStr = join ("\n", map {$_->toString(%flags)} $proofs->[$row]->getTriples());
	    $tr->addRow($proofStr);
	    if ($row < @$rows-1) {
		$tr->underline();
	    }
	}
    }

    my $nsStr = $nsHandler ? $nsHandler->toString(%flags)."\n" : '';
    return $nsStr.$tr->toString."\n";
}

sub RSRenderer {
    my ($self, $rows, $selects, $nodes) = @_;
    my $nsh = new W3C::Util::NamespaceInventor(-relay => $self->{-context}->getNamespaceHandler());
    print "\@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\@prefix rs:     <http://jena.hpl.hp.com/2003/03/result-set#> .\n\n[] rdf:type rs:ResultSet ;\n";
    for (my $iCol = 0; $iCol < @$selects; $iCol++) {
	print "    rs:resultVariable \"$selects->[$iCol]\" ;\n"
    }
    my $rowCount = @$rows;
    my $punct = @$rows ? ';' : '.';
    print "    rs:size \"$rowCount\" $punct\n";
    my $genIds = {};
    for (my $iRow = 0; $iRow < @$rows; $iRow++) {
	print "    rs:solution\n        [ rdf:type rs:ResultSolution ;\n";
	for (my $iCol = 0; $iCol < @$selects; $iCol++) {
	    my $value = $rows->[$iRow][$iCol];
	    my $predicate = 'value';
	    if (UNIVERSAL::isa($value, 'W3C::Rdf::Uri')) {
		$value = '<'.$value->getUri.'>';
	    } elsif (UNIVERSAL::isa($value, 'W3C::Rdf::String')) {
		$value = '"'.$value->getString.'"';
	    } elsif (UNIVERSAL::isa($value, 'W3C::Rdf::BNode')) {
		my $t = $genIds->{$value};
		if (!$t) {
		    $genIds->{$value} = $t = keys (%{$genIds}) + 1;
		}
		$value = '_:'.$t;
	    } elsif ($value == $Value_NULL) {
		$predicate = 'nonValue';
		$value = "\"NULL\"";
	    } else {
		&throw(new W3C::Util::ProgramFlowException());
	    }
	    $punct = $iCol < @$selects-1 ? ';' : '';
	    print "          rs:binding [ rdf:type rs:ResultBinding ;\n                       rs:variable \"$selects->[$iCol]\" ; rs:$predicate $value ] $punct\n";
	}
	$punct = $iRow < @$rows-1 ? ';' : '.';
	print "        ] $punct\n"
    }
}

sub showRdf {
    my ($self, $statements, $serializer, $resource, $nsMap) = @_;
    my $result;

    {
	my $aggregate = $self->{-context}->getNamespaceHandler();

	foreach my $qname (keys %{$self->{-queryHandler}{NAMESPACES}}) {
	    my $uri = $self->{-queryHandler}{NAMESPACES}{$qname};
	    $aggregate->addNamespace($qname, $uri, $resource);
	}

	foreach my $ns (keys %$nsMap) {
	    $aggregate->addNamespace($ns, $nsMap->{$ns}, $resource);
	}
    }

    my $iterator = $self->{-context}->getRdfDB()->makeSerializerIterator($statements, 
							   {-scheme => 'guess', 
							    -ignoreReifications => 1, 
							    -ignoreAnonymousReifications => 1, 
							    # -exceptionHandler => 
							    #     new W3C::Rdf::RdfDB::Serializer::ExceptionIgnorer
							});
    eval {
	$iterator->iterate($serializer);
	$result = $serializer->getText();
    }; if ($@) {
	if (my $ex = &catch('W3C::Util::Exception')) {
	    $result = $ex->toString;
	} else {
	    $result = "died with $@";
	}
    }
    return $result;
}

__END__

=head1 NAME

algae - command line script access to the Algae query engine.

=head1 SYNOPSIS

algae [options] [file ...]

=head1 OPTIONS

=over 8

=item B<-l|lang>

Language name of next query (eg. BRQL, RDQL, Algae, SeRQL)

=item B<-i|input>

Language name of next data file (eg. RDFXML, n3)

=item B<-reportClass> class

Generate results in the form of B<class>.

=item B<-reportParms> ...

See examples.

=item B<-forceHost> host

Force relative URIs to use host B<host> rather than the current machine's hostname.

=item B<-forcePath> path

Force relative URIs to use the path B<host> rather than the current working directory.

=item B<-o> file

Place output in file B<file>.

=item B<-d|read> file

Read data from file B<file>.

=item B<-f|query> file

Read query from file B<file>.

=item B<-help>

Print a brief help message and exit.

=item B<-man>

Send the manual page to the $PAGER and exit.

=item B<file>

Parse B<file> and put resuls into the B<current database>.

=back

=head1 DESCRIPTION

B<algae> reads a series of queries in any of the B<supported languages>.

This module is part of the W3C::Rdf CPAN module.

=head1 AUTHOR

Eric Prud'hommeaux <eric@w3.org>

=head1 SEE ALSO

L<W3C::Rdf::Algae2>
L<W3C::Rdf::RdfDB>

=head1 COPYRIGHT

Copyright Massachusetts Institute of technology, 1998.

THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS
OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR
FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE
ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. 

COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION. 

The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining 
to the software without specific, written prior permission. Title to copyright in this software and 
any associated documentation will at all times remain with copyright holders. 

=cut

