#Copyright Massachusetts Institute of technology, 1998.
#Written by Eric Prud'hommeaux for the World Wide Web Consortium

# $Id: StatementsSerializer.pm,v 1.14 2007/03/11 02:19:05 eric Exp $

use strict;
require Exporter;
#require AutoLoader;

use W3C::Rdf::EmitterInterface;

$W3C::Rdf::RdfDB::REVISION = '$Id: StatementsSerializer.pm,v 1.14 2007/03/11 02:19:05 eric Exp $ ';

package W3C::Rdf::StatementsSerializer;
use vars qw($VERSION $DSLI @ISA @TODO @EXPORT_OK);
@ISA = qw(W3C::Util::NamedParmObject Exporter); # AutoLoader);
@TODO = qw();
@EXPORT_OK = qw();
$VERSION = 0.95;
$DSLI = 'adpO';
use W3C::Util::Exception;
use W3C::Rdf::Atoms qw(&atomSort);
use W3C::Util::ArrayUtils qw(&DecorateArray);

sub new {
    my ($proto, @parms) = @_;
    my $class = ref($proto) || $proto;
    my $self = $class->SUPER::new(@parms);
    if (!defined $self->{-text}) {
	$self->{-text} = [];
    }
    if (!defined $self->{-prefixes}) {
	$self->{-prefixes} = {};
    }
    return $self;
}

sub setIterator {
    my ($self, $iterator) = @_;
    $self->{-iterator} = $iterator;
}

sub getNamespaceHandler {
    my ($self) = @_;
    return $self->{-namespaceHandler};
}

sub nest {
    return 0;
}

sub collection {
    return 0;
}

sub getText {
    my ($self) = @_;
    my @nsDecls = map {"$_: $self->{-prefixes}{$_}"} keys %{$self->{-prefixes}};
    return join ("\n", @nsDecls, @{$self->{-text}}, undef);
}

sub startDocument {
    my ($self) = @_;
}

sub endDocument {
    my ($self) = @_;
}

sub serializeStatements {
    my ($self, $withThisSubject, $forceAbout) = @_;

    # Get the output mode from the -outputMode constructor arg.
    # Set this with -sParm-outputMode=n3
    my %flags = (-outputMode => $self->{-outputMode});
    my $nsr = new W3C::Util::NamespaceReducer(-relay => $self->{-importMap});
    my @sortedStatements = (sort {&atomSort($a->getPredicate, $b->getPredicate) || 
				  &atomSort($a->getSubject, $b->getSubject) || 
				  &atomSort($a->getObject, $b->getObject)} @$withThisSubject);

    # Pretty up the output which will be in an array of lines.
    my ($firstLeader, $nthLeader, $nthTrailer, $lastTrailer) = 
	$flags{-outputMode} eq 'n3' ? 
	('(', ' ', ',', ') .') : 
	('', '', ',', '');
    my @serializedStatements;
    for (my $i = 0; $i < @sortedStatements; $i++)  {
	my $trailer = $i < @sortedStatements - 1 ? $nthTrailer : $lastTrailer;
	push (@serializedStatements, 
	      &DecorateArray('', '', '', $trailer,
			     $sortedStatements[$i]->toString(%flags, 
						   -namespaceHandler => $nsr)));
    }

    # Store the namespace declaration header...
    push (@{$self->{-text}}, $flags{-outputMode} eq 'n3' ? 
	  $nsr->toString(%flags) : 
	  &DecorateArray('( ', '  ', '', ' )', $nsr->toString(%flags)));
    # ... and each line of the proof.
    push (@{$self->{-text}}, &DecorateArray($firstLeader, $nthLeader, '', '', @serializedStatements));
}

1;

__END__

=head1 NAME

W3C::Rdf::StatementsSerializer - serialize RDF graphs in line-oriented statements format

=head1 SYNOPSIS

  use W3C::Rdf::Atoms;
  use W3C::Rdf::RdfDB;
  require W3C::Rdf::StatementsSerializer;
  my $atoms = new W3C::Rdf::Atoms();
  my $rdfDB = new W3C::Rdf::RdfDB(-atomDictionary => $atoms);
  my $algae2 = new W3C::Rdf::Algae2(-atomDictionary => $atoms);
  my $serializer = new W3C::Rdf::StatementsSerializer(-atomDictionary => $atoms);
  my $iterator = $rdfDB->makeSerializerIterator($statements, $algae2);
  $iterator->iterate($serializer);
  print $serializer->getText();

=head1 DESCRIPTION

C<W3C::Rdf::RdfDB>'s C<W3C::Rdf::RdfDB::SerializerIterator> calls
C<W3C::Rdf::StatementsSerializer> to a line-oriented list of statements.
The statements format includes provenance information.

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

=head1 CONSTRUCTOR

=over 4

=item new ( ATOMS [, FLAGS] )

Creates an C<W3C::Rdf::StatementsSerializer>.  This must be passed an Atoms dictionary.
Attitional flags:

=back

=head1 METHODS

=over 4

=item collection()

Return whether this serializer has special code for collections. If so,
C<serializeStatements> may be called with a C<W3C::Rdf::Atoms::ListStatement>.

=item nest()

Return whether this serializer can express nested descriptions.

=item startDocument()

Follow SAX convention except there is no document locator (the serializer is
the actual owner of the document).

=item endDocument()

Follow SAX convention.

=item serializeStatements( STATEMENTS, [ ITERATOR ] )

Take a set of statements to be serialized. The C<ITERATOR> is only used if the
serializer attempts to serialize nested (statements with a subject of the
current object). The C<STATENTS> may also be ListStatemens, in which case
special code serializes a collection.

=item getText()

Return a scalar with the serialized RDF statements.

=back

=head1 AUTHOR

Eric Prud'hommeaux <eric@w3.org>

=head1 SEE ALSO

L<W3C::Rdf::RdfDB>

=cut
