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

# $Id: FileSystemDB.pm,v 1.4 2004/10/17 19:10:53 eric Exp $

# described in http://www.w3.org/2004/10/16-RDF-FileSystem/
# schema in http://www.w3.org/2004/10/16-RDF-FileSystem/ns

use strict;
require Exporter;

$W3C::Rdf::FileSystemDB::REVISION = '$Id: FileSystemDB.pm,v 1.4 2004/10/17 19:10:53 eric Exp $ ';

package W3C::Rdf::FileSystemDB;
use CGI qw(&escape);
use vars qw($VERSION $DSLI @ISA @EXPORT @EXPORT_OK $NS $pNode $pUri $pString);
@ISA = qw(Exporter);
@EXPORT = qw();
$VERSION = 0.94;
$DSLI = 'adpO';

$NS = 'http://www.w3.org/2004/10/16-RDF-FileSystem/ns#';

use Net::Telnet;

use W3C::Rdf::RdfDB;
package W3C::Rdf::FileSystemDB;
@W3C::Rdf::FileSystemDB::ISA = qw(W3C::Rdf::RdfDB);
use W3C::Util::Exception;
use W3C::Rdf::Atoms qw($ATTRIB_GroundFact);

sub new {
    my ($proto, @parms) = @_;
    my $class = ref($proto) || $proto;
    my $self = $class->SUPER::new(@parms);

    # Constant Predicates:
    $pNode = $self->{-atomDictionary}->getUri("${NS}dirEnt");
    $pUri = $self->{-atomDictionary}->getUri("${NS}resource");
    $pString = $self->{-atomDictionary}->getUri("${NS}filename");

    return $self;
}

sub dbEvaluateQTerm {
    my ($self, $resultSet, $exprs, $dbSpec) = @_;
    $self->_walkQuery($exprs, 0, 0, 0);
    $self->SUPER::dbEvaluateQTerm($resultSet, $exprs, $dbSpec);
}

sub _walkQuery {
    my ($self, $term, $disjunction, $negation, $outer) = @_;
    my $ret;
    if ($term->isa('W3C::Rdf::AlgaeCompileTree::Decl')) {
	my ($p, $s, $o) = map {$term->getSlot($_)->lookfor} qw(0, 1, 2);
	if ($p->getUri =~ m|^\Q$NS\EdirEnt$|) {
	    my $sUriStr = $s->getUri;
	    if ($sUriStr =~ m|^file://([^/]+)(/.*)$|) {
		my ($host, $path) = ($1, $2);
		$self->_readDir($s, $host, $path);
	    } elsif ($sUriStr =~ m|^http://([^/]+)(/.*)$|) {
		&throw(new W3C::Util::Exception(-message => "HTTP walk not enabled - not walking $sUriStr"));
	    } else {
		&throw(new W3C::Util::Exception(-message => "refusing to do unbound directory walk"));
	    }
	}
    } elsif ($term->isa('W3C::Rdf::AlgaeCompileTree::BinaryDecl')) {
	my $l = $self->_walkQuery($term->getLeft, $disjunction, $negation, $outer);
	my $r = $self->_walkQuery($term->getRight, $disjunction, $negation, $outer);
    } elsif ($term->isa('W3C::Rdf::AlgaeCompileTree::Negation')) {
	$ret = $self->_walkQuery($term->getDecl(), $disjunction, !$negation, $outer);
    } elsif ($term->isa('W3C::Rdf::AlgaeCompileTree::Option')) {
	$ret = $self->_walkQuery($term->getDecl(), $disjunction, $negation, 1);
    } else {
	&throw(new W3C::Util::ProgramFlowException());
    }
    return $ret;
}

sub _readDir {
    my ($self, $s, $host, $path) = @_;
    my @results;
    my $a = $self->{-sourceAttribution};
    if (!$a) {
	$a = $self->{-atomDictionary}->getGroundFactAttribution($s, undef, undef, undef);
    }

    if (!opendir(DIR, $path)) {
	&throw(new W3C::Util::Exception(-message => "can't opendir $path: $!"));
    }
    foreach my $file (readdir(DIR)) {

	my $node1 = $self->{-atomDictionary}->createBNode($a);
	my $arcNode = $self->{-atomDictionary}->getStatement($pNode, $s, $node1, undef);
	$arcNode->getAttributionList->ensureDirectAttribution($a);
	push (@results, $arcNode);

	my $fileUri = $self->{-atomDictionary}->getUri(&CGI::escape($file), $s);
	my $arcUri = $self->{-atomDictionary}->getStatement($pUri, $node1, $fileUri, undef);
	$arcUri->getAttributionList->ensureDirectAttribution($a);
	push (@results, $arcUri);

	my $fileString = $self->{-atomDictionary}->getString($file, undef, 'PLAIN');
	my $arcString = $self->{-atomDictionary}->getStatement($pString, $node1, $fileString, undef);
	$arcString->getAttributionList->ensureDirectAttribution($a);
	push (@results, $arcString);
    }
    closedir DIR;
    foreach my $triple (@results) {
	$self->addTriple($triple);
    }
}

1;

__END__

=head1 NAME

W3C::Rdf::ObjectDB - RDF DB mapping to file system access

=head1 SYNOPSIS

  use W3C::Rdf::FileSystemDB;
  my $FileSystemDB = new W3C::Rdf::FileSystemDB(-atomDictionary => $atoms);

    ns fs=<http://www.w3.org/2004/10/16-RDF-FileSystem/ns#>
    attach fs:FSDB ?fs ()
    ask ?fs (<file://localhost/tmp/> fs:dirEnt ?dirEnt.)
    collect (?dirEnt)

    ns fs=<http://www.w3.org/2004/10/16-RDF-FileSystem/ns#>
    attach fs:FSDB ?fs ()
    ask ?fs (<file://localhost/tmp/> fs:dirEnt ?dirEnt.
             ?dirEnt fs:resource ?resource.
             ?dirEnt fs:filename ?filename)
    collect (?filename ?resource)


=head1 DESCRIPTION

C<W3C::Rdf::FileSystemDB> is an RDF database following the C<W3C::Rdf::RdfDB>
interface. This access to the filesystem such as directories and file contents.

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

=head1 AUTHOR

Eric Prud'hommeaux <eric@w3.org>

=head1 SEE ALSO

C<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
