#!/usr/local/bin/perl -w use strict; use lib "../../11/15/perl-rdf-dumper"; use RDF::Pool; # see http://www.w3.org/2001/11/15/perl-rdf-dumper use Data::Dumper; my $tmp = ($ENV{SEMRUN_TMP} || "/tmp/semrun-tmp") . "$$"; my $debug; my $primaryAddress; my $language; my $rdfns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"; my $srns="http://www.w3.org/2001/12/semrun/ont-1#"; my $bnodes; my $uuid = `uuidgen -t`; chomp $uuid; my $bnode_counter = 0; my $keep_files; while (@ARGV) { my $arg = shift @ARGV; if ($arg eq "--language" || $arg eq "-L") { $language = shift @ARGV; next; } if ($arg eq "--keep-files") { $keep_files = 1; next; } if ($arg eq "--tmp" || $arg eq "-T") { $tmp = shift @ARGV; next; } if ($arg eq "--debug" || $arg eq "-d") { $debug = 1; next; } if ($arg !~ "^-") { $primaryAddress = $arg; if (@ARGV) { $primaryAddress = undef; } last; } } unless($primaryAddress) { print STDERR "usage: $0 [--tmp prefix] [--debug] [--language lang] uri\n"; exit(1); } # print "Packages: ", join(", ", available_action_classes), "\n"; my $support_file = "$tmp.support.P"; writeSupport(); my $current_rdf_file = "$tmp.current.P"; print STDERR "current+rdf_file = $current_rdf_file\n" if $keep_files; open(F, ">>$current_rdf_file"); my $givens = RDF::Pool->new($srns); $givens->{triple_hook} = \&print_prolog; $givens->load($primaryAddress); if (0) { my $self = bless { pid=>$$, user=>$ENV{USER}, starttime=>time }, "Executor"; chomp($self->{hostname} = `hostname`); $self->{revision} = deCVS('$Revision: 1.3 $'); $self->{revisionDate} = deCVS('$Date: 2001/12/19 04:37:29 $'); $self->{program} = deCVS('$Source: /w3ccvs/WWW/2001/12/semrun/semrun,v $'); $givens->add($self); #writeCurrent; $givens->forEachTriple(\&print_prolog); ## too buggy } print F ":- dynamic drdf/3.\n"; print F "rdf(A,B,C) :- drdf(A,B,C).\n"; close(F); run(); # find all things that can go to our agents, and send 'em there exit(0); sub print_prolog { my ($s,$p,$o) = @_; return unless $s; print STDERR "Got triple: ($s) ($p) ($o)\n"; printf F "rdf(%s, %s, %s).\n", prolog_term($s), prolog_term($p), prolog_term($o); return 1; } ################################################################ sub deCVS { my $in = shift; $in =~ s/^\S*\s(.*)\s*\$$/$1/e; return $in; } sub run { my %commands; my $execview = RDF::Pool->new($srns); $execview->add_prefix("_person_", "http://example.com/Person#"); my $xsb_command = "xsb --quietload --noprompt --nobanner -e \"['$current_rdf_file'], ['$support_file'], findall(X, (rdf(X, '${rdfns}type', '${srns}Import');rdf(X, '${rdfns}type', '${srns}Conditional');rdf(X, '${rdfns}type', '${srns}Request')), ResultList), writeNTrObjects(ResultList, 5), halt.\" | tee /tmp/blackboard.debug |"; # my $xsb_command = "xsb --quietload --noprompt --nobanner -e \"['$current_rdf_file'], ['$support_file'], findall(X, rdf(X, '${srns}for', '${srns}you'), ResultList), writeNTrObjects(ResultList, 5), halt.\" | tee /tmp/blackboard.debug |"; #print "Command: $xsb_command\n"; my @commands = $execview->load_ntriples($xsb_command, undef, undef, "^no"); # use aCommandFor $me ? then dispatch on class? foreach my $c (@commands) { next if ref($c) eq "HASH"; # unblessed....? fix RDF::Pool if ($c->isa('Conditional') || $c->isa('Imports') || $c->isa('Request')) { print Dumper($c) . "\n"; eval { $c->run(); }; if ($@) { # hrm... what to do about a failure? print STDERR "Command run failed: $@\n"; } } } } ################################################################ ################################################################ sub writeSupport { open(C, ">" . $support_file) || die("can't write $support_file: $!\n"); print C <<"_END"; :- dynamic(written/1). writeNTrObjects([], _) :- true. writeNTrObjects([H|T], Depth) :- writeNTrObject(H, Depth), writeNTrObjects(T, Depth). writeNTrObject(ID, Depth) :- (written(ID), write('# already wrote '), writeln(ID)); ( assert(written(ID)), NewDepth is Depth - 1, write('# writing new object: '), write(ID), write(' depth-left='), writeln(NewDepth), ( NewDepth > 0, findall(rdf(ID, P, O), rdf(ID, P, O), Statements), writeNTrStatementList(Statements, NewDepth) ) ; write('# too deep to write object'), put(10)). writeNTrStatementList([], _) :- true. writeNTrStatementList([rdf(S, P, O) | Rest], Depth) :- writeNTrStatement(S, P, O), write('# lets try writing the property '), writeln(P), writeNTrObject(P, Depth), write('# lets try writing the value '), writeln(O), writeNTrObject(O, Depth), writeNTrStatementList(Rest, Depth). writeNTrStatement(S, P, O) :- writeNTrTerm(S), write(' '), writeNTrTerm(P), write(' '), writeNTrTerm(O), write('.'), put(10). writeNTrTerm(X) :- atom(X), write('<'), write(X), write('>'); put(34), writeNTrString(X), put(34). % backslash writeNTrString([92 | Rest]) :- put(92), put(92), writeNTrString(Rest). % quote writeNTrString([34 | Rest]) :- put(92), put(34), writeNTrString(Rest). % newline writeNTrString([10 | Rest]) :- put(92), write('n'), writeNTrString(Rest). % some others? % unicode? writeNTrString([Char | Rest]) :- put(Char), writeNTrString(Rest). writeNTrString([]) :- true . _END close(C); } #sub print_prolog { # my ($s,$p,$o) = @_; # return unless $s; # print STDERR "Got triple: ($s) ($p) ($o)\n"; # printf F "rdf(%s, %s, %s).\n", prolog_term($s), prolog_term($p), prolog_term($o); #} sub prolog_term { my $name = shift; # "literal" if ($name =~ m/^"(.*)"$/) { # Unicode?! # funny chars? # ... if any, then do array form? return "\"" . $1 . "\""; } # _:bNode? if ($name =~ m/^_:(.*)/) { if (exists $bnodes->{$name}) { return $bnodes->{$name}; } my $result = "'urn:uuid:$uuid:" . $bnode_counter++ . "'"; $bnodes->{$name} = $result; return $result; } # if ($name =~ m/^<(.*)>$/) { $name = "'" . $1 . "'"; return $name; } } ################################################################ ################################################################ package Conditional; sub run { my $this = shift; my @vars = RDF::Pool::elements($this->{forAll}); print "Conditional ForAll: "; foreach my $v (@vars) { print $v->{_rdf_identifier} . " "; $v->{__UNIV} = 1; } print "\n"; my $count = 0; for my $var (@vars) { die if ($var->{__var}); $var->{__var} = $var->{_rdf_identifier}; $var->{_rdf_identifier} = sprintf("$%d", $count++); } open(F, ">>$current_rdf_file"); print F "% Conditional ".$this->{_rdf_identifier}."\n"; printf F ("rdf(%s, %s, %s) :-\n", main::prolog_term($this->{then}->{statements}->{_daml_first}->{_rdf_subject}->{_rdf_identifier}), main::prolog_term($this->{then}->{statements}->{_daml_first}->{_rdf_predicate}->{_rdf_identifier}), main::prolog_term($this->{then}->{statements}->{_daml_first}->{_rdf_object}->{_rdf_identifier})); my @ifs = RDF::Pool::elements($this->{if}->{statements}); for my $s (@ifs) { printf F (" rdf(%s, %s, %s),\n", main::prolog_term($s->{_rdf_subject}->{_rdf_identifier}), main::prolog_term($s->{_rdf_predicate}->{_rdf_identifier}), main::prolog_term($s->{_rdf_object}->{_rdf_identifier})); } print F " true.\n\n"; close(F); for my $var (@vars) { $var->{_rdf_identifier} = $var->{__var}; delete $var->{__var}; } } package Request; sub run { my $this = shift; print "Request for action of class: " . ref($this->{action}); return 1; } package Imports; sub run { my $this = shift; } package Test; BEGIN { unshift @main::available_action_classes, __PACKAGE__; } sub run { my $this = shift; print "Test command is running!\n"; } package RequestToDisplayText; BEGIN { unshift @main::available_action_classes, __PACKAGE__; } sub run { my $this = shift; printf "Requested Output: %s\n", $this->{text}; } package DatalogRule; BEGIN { unshift @main::available_action_classes, __PACKAGE__; } sub run { my $this = shift; printf "Requested Output: %s\n", $this->{text}; my $vars = RDF::Pool->arrayFromDamlList($this->{forAll}); my $count = 0; for my $var (@$vars) { die if ($var->{__var}); $var->{__var} = $var->{rdfid}; $var->{rdfid} = sprintf("$%d", $count++); } open(F, ">>$current_rdf_file"); print "% DatalogRule ".$this->{rdfid}."\n"; printf F ("rdf(%s, %s, %s) :-\n", prolog_term($this->{then}->{_rdf_subject}->{rdfid}), prolog_term($this->{then}->{_rdf_predicate}->{rdfid}), prolog_term($this->{then}->{_rdf_object}->{rdfid})); my $ifs = RDF::Pool->arrayFromDamlList($this->{if}->{enumeration}); for my $s (@$ifs) { printf F (" rdf(%s, %s, %s),\n", prolog_term($s->{_rdf_subject}->{rdfid}), prolog_term($s->{_rdf_predicate}->{rdfid}), prolog_term($s->{_rdf_object}->{rdfid})); } print F " true.\n\n"; close(F); for my $var (@$vars) { $var->{rdfid} = $var->{__var}; delete $var->{__var}; } } package Shutdown; BEGIN { unshift @main::available_action_classes, __PACKAGE__; } sub run { my $this = shift; print STDERR "Blackboard shutdown"; my $who = $this->{by}->{_person_name}; if ($who) { print STDERR " by \"", $who, "\""; } my $why = $this->{reason}; if ($why) { print STDERR " for \"", $why, "\""; } print STDERR "\n"; exit(1); } package PleaseSendMail; BEGIN { unshift @main::available_action_classes, __PACKAGE__; } sub run { my $this = shift; use Net::SMTP; my $from = $this->{from}; my $to = $this->{to}; my $text = $this->{text}; my $smtp = Net::SMTP->new('127.0.0.1'); $smtp->mail($from); $smtp->to($to); $smtp->data(); $smtp->datasend("To: $to\n"); $smtp->datasend("\n"); $smtp->datasend($text); $smtp->dataend(); $smtp->quit; print STDERR "Mail sent ($from) -> ($to)\n"; } __END__ who do we trust? ONE policy per blackboard? Or multiple policies on the same blackboard? Does Zakim have his own blackboard? Which is included on this one? mostly its about bridging rules. signed email. f-a-s as input stream zakim input stream? UDP notification of "include". Zakim wants to say "here's the current state" ie: update zakim_now to [ ... ] __END__ # add information about this process? # start time, user, pid, host, ways to reach it, user admin, policies if ($arg eq "--insert") { my $file = shift @ARGV; open(F, ">>$current_rdf_file"); my $xp = RDF::Pool->new(); $xp->{triple_hook} = \&print_prolog; $xp->load($file); close(F); $something_done = 1; } if ($arg eq "--export") { my $file = shift @ARGV; my $pool = RDF::Pool->new($srns); my $xsb_command = "xsb --quietload --noprompt --nobanner -e \"['$current_rdf_file'], ['$command_query_file'], findall(X, rdf(X, Y, Z), ResultList), writeNTrObjects(ResultList, 5), halt.\" | tee /tmp/blackboard.debug |"; $pool->load_ntriples($xsb_command, undef, undef, "^no"); $pool->save_rdfxml_file($file); $something_done = 1; } if ($arg eq "--run") { my %commands; my $pool = RDF::Pool->new($srns); $pool->add_prefix("_person_", "http://example.com/Person#"); my $xsb_command = "xsb --quietload --noprompt --nobanner -e \"['$current_rdf_file'], ['$command_query_file'], findall(X, rdf(X, '${srns}for', '${srns}you'), ResultList), writeNTrObjects(ResultList, 5), halt.\" | tee /tmp/blackboard.debug |"; #print "Command: $xsb_command\n"; my @commands = $pool->load_ntriples($xsb_command, undef, undef, "^no"); # use aCommandFor $me ? then dispatch on class? foreach my $c (@commands) { print Dumper($c) . "\n"; eval { $c->run(); }; if ($@) { # hrm... what to do about a failure? print STDERR "Command run failed: $@\n"; } $something_done = 1; } } if ($arg eq "--schema") { my $file = shift @ARGV; my $pool = RDF::Pool->new($srns); my $xsb_command = "xsb --quietload --noprompt --nobanner -e \"['$current_rdf_file'], ['$command_query_file'], findall(X, rdf(X, Y, Z), ResultList), writeNTrObjects(ResultList, 5), halt.\" | tee /tmp/blackboard.debug |"; my @triples; my %type; $pool->{triple_hook} = sub { my ($s, $p, $o) = @_; push @triples, [$s, $p, $o]; #print $p."\n"; if ($p eq "<${rdfns}type>") { $type{$s} = $o; #print "YES $s, $o\n\n"; } if ($o =~ m/^\"/) { $type{$o} = "literal"; } return undef; }; $pool->load_ntriples($xsb_command, undef, undef, "^no"); my %domainPairs; my %rangePairs; foreach my $triple (@triples) { my ($s, $p, $o) = @$triple; if ($type{$s}) { my $t = $type{$s}; #print "domain type of $s is $t\n"; $domainPairs{"$t $p"}++; } if ($type{$o}) { my $t = $type{$o}; #print "range type of $o is $t\n"; $rangePairs{"$t $p"}++; } } foreach my $d (keys %domainPairs) { print "Domain Pair: $d\n"; } foreach my $d (keys %rangePairs) { print "Range Pair: $d\n"; } $something_done = 1; } } unless ($something_done) { print STDERR "usage: $0 [--database uri] [--insert uri] [--export uri] [--run]\n"; } exit(0); sub insert_text { my $text = shift; my $stext = $text; $stext =~ s/\"[^\"]\"//g; # remove any quoted text if ( ! $language && $stext =~ m/<(\w+:)?RDF( |>)/ ) { $language = "xmlrdf"; } if ( ! $language && $stext =~ m/[\(\),;{}\[\]]/ ) { $language = "n3"; $text = "\@prefix bb: <$srns>.\n" . $text; } if ( ! $language ) { $language = "nt"; } my $tmp = $primary . "arg_text." . $language; print "Using tmp file for text: $tmp\n"; open(F, ">".$tmp) or die; print F $text; close(F); insert_from_URI($tmp); } sub insert_from_URI { my $addr = shift; open(F, ">>$current_rdf_file"); my $xp = RDF::Pool->new(); $xp->{triple_hook} = \&print_prolog; $xp->load($addr); close(F); }