
:- ensure_loaded(library('semweb/rdf_db')).

file_search_path(semwalker, '/home/sandro/semwalker').
:- ensure_loaded(semwalker(qtest)).
:- ensure_loaded(semwalker(must)).
:- ensure_loaded(semwalker(findsome)).
:- ensure_loaded(semwalker(html)).

:- dynamic ns/2.      % ns(Shortname, Longname)
:- dynamic this_ns/1. % ie shortname ''
:- dynamic class/2.

%   	rdf_load('/tmp/asn.rdf').

go_owl :-
	go('http://www.w3.org/2002/07/owl#').

load_foaf :-
	rdf_load('foaf.rdf').

go_foaf :-
	go('http://xmlns.com/foaf/0.1/').

load_rif :-
	rdf_load('/home/sandro/workspace/hierdoc/rif-core.rdf').

go_rif :-
	go('http://www.w3.org/2006/11/rif-core#').

go(NS) :-
	make_this(NS),
	go.

make_this(NS) :-
	retractall(this_ns(_)),
	assert(this_ns(NS)).
	

portray(Id) :-
	atom(Id), 
	atom_concat('http://', _, Id),
	qname(Id, Q),
	write(Q).

qname(URI, Q) :-
	rdf_split_url(Long, Local, URI),
	(   this_ns(Long)
	->  Q = Local
	;   (   ns(Short, Long)
	    ->  true
	    ;   gensym(ns, Short),
		assert(ns(Short, Long))
	    ),
	    Q = (Short:Local)
	).

ns(rdfs, 'http://www.w3.org/2000/01/rdf-schema#').
ns(foaf, 'http://xmlns.com/foaf/0.1/').
ns(vcard, 'http://www.w3.org/2006/vcard/ns#').
ns(dc, 'http://purl.org/dc/elements/1.1/').
ns(owl, 'http://www.w3.org/2002/07/owl#').
ns(rdf, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#').
ns(xsd, 'http://www.w3.org/2001/XMLSchema#').
ns(wordnet, 'http://xmlns.com/wordnet/1.6/').

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ours(Term) :-
	this_ns(Prefix),
	rdf_split_url(Prefix, _Local, Term).

root_class(Class) :-
	class(Class),
%	ours(Class),    % we want this if we're not using sub.
	\+ sub(Class, _).

sub(Class, Super) :-
	% fail,
	direct_superclass(Class, Super),
	(   sub(Super, _)
	;   root_class(Super)
	),
	once(direct_superclass(Class, FirstSuper)),
	FirstSuper = Super.


inherits(Class, Super) :-
	direct_superclass(Class, Super),
	\+ sub(Class, Super).

        %split_inherits(Class, _, Supers),
	%member(Super, Supers).

% Pick one of the direst superclasses as primary, so we can nest under it.
% The logic here is about human usability.  It does not effect semantics.
split_inherits(Sub, PrimarySuper, OtherSupers) :-
	findall([Rank, Super],
		(   direct_superclass(Sub, Super),
		    superclass_quality(Sub, Super, Rank)
		),
		Unsorted),
	Unsorted = [_|_],   % make we have at least one
	sort(Unsorted, Sorted),
	maplist(second, Sorted, Supers),
	Supers = [PrimarySuper | OtherSupers].

second([_,B], B).

superclass_quality(_Sub, Super, 10) :-
	ours(Super), !.
superclass_quality(_Sub, _Super, 1).



uninherited_property(Class, Property) :-
	property(Class, Property),
	forall(superclass(Class, Super),
	       \+ property(Super, Property)).

/*
is_property(Foo).
name(Property, Name).
is_SingleValuedProperty(P).
type(P, Type).
is_ListValuedProperty(P).
elementType(P, Type).
is_MultiValuedProperty(P).
type(P, Type).
*/




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Open World Data Views 

%% superclass(?Class, ?Superclass)
% superclass(Class, Class).
given_superclass(Class, Superclass) :-
	rdf(Class, rdfs:subClassOf, Superclass).
inferred_superclass(Class, Superclass) :-
	given_superclass(Class, Intermediate),
	superclass(Intermediate, Superclass).
%inferred_superclass(_Class,
%		    'http://www.w3.org/1999/02/22-rdf-syntax-ns#Resource').
superclass(A, B) :-
	given_superclass(A,B),
	A \= B.
superclass(A, B) :-
	inferred_superclass(A,B),
	A \= B.

%% class(?Class)
class(Class) :-
	rdf(_, rdfs:domain, Class).
%class(Class) :-                      this doesn't count, really....
%	rdf(_, rdfs:range, Class).
class(Class) :-
	rdf(_, rdfs:subClassOf, Class).
class(Class) :-
	rdf(Class, rdfs:subClassOf, _).
class(Class) :-
	rdf(_, rdf:type, Class).
class(Class) :-
	rdf(Class, rdf:type, rdfs:'Class'). 
class(Class) :-
	rdf(Class, rdf:type, owl:'Class').
class('http://www.w3.org/1999/02/22-rdf-syntax-ns#Resource').

%% properties(?Class, ?Property)
property(Class, Property) :-
	rdf(Property, rdfs:domain, Class).
property(Class, Property) :-
	rdf(Property, rdfs:domain, Superclass),
	superclass(Class, Superclass).
%   this isn't quite right.
%property('http://www.w3.org/1999/02/22-rdf-syntax-ns#Resource', P) :-
%	rdf(P, rdf:type, rdf:'Property').
	 
%%% NEED SUPERPROPERTY REASONING


range(Property, Class) :-
	rdf(Property, rdfs:range, Class).
        % should do inference and use leaf, I guess.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Closed World Data Views

%% direct_superclass(?Class, ?Superclass)
direct_superclass(Class, Superclass) :-
	superclass(Class,Superclass),
	\+ intervening_class(Class, Superclass).

intervening_class(Class, Superclass) :-
	superclass(Class, Intervening),
	superclass(Intervening, Superclass).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

go :-
	setofsome(1000, _Done,
		  Class,
		  root_class(Class),
		  Classes),
	forall(member(Class, Classes),
	       write_class(Class, '', [])
	      ).

% a var is a kind of expr and a kind of term

write_class(Class, Prefix, Supers) :-
	atom_concat(Prefix, '   ', NextPrefix),
	format('~n~p~p', [Prefix, Class]),
	forall(( inherits(Class, Super) %,
	%	 \+ member(Super, Supers)
	       ),
	       format(', inherits ~p', Super)
	      ),
	format('~n', []),
	findall(P, uninherited_property(Class, P), Psu),
	sort(Psu, Ps),
	forall(member(Property, Ps),
	       (
		 (   range(Property, Range)
		 ->  true
		 ;   Range = unknown
		 ),
		 format('~w~p : ~p~n', [NextPrefix, Property, Range])
	       )
	      ),
	findall(Sub, sub(Sub, Class), Subs),
	sort(Subs, SubsSorted),
	forall(member(Sub, SubsSorted),
	       write_class(Sub, NextPrefix, [Class|Supers])
	      ).
