:-use_module(library('semweb/rdf_db')).
:-use_module(library('semweb/rdfs')).



 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%  ODM PROLOG TRANSFORMER 
%  Author: Jesus Almendros and Luis Iribarne. March 2012
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


load_op:- 
	op(1080,xfy,[@]),
	op(1090,xfy,[and]),
	op(1070,xfy,[&]),
	op(1000,fx,[#]).

:-load_op.

:-multifile (@)/2.
:-multifile (and)/2.
:-style_check(-discontiguous).

%%%%%%%%%%%%%%%%%%%%%%%%
% NAMESPACES HANDLING
%%%%%%%%%%%%%%%%%%%%%%%

rdf_db:ns(rdf,  'http://www.w3.org/1999/02/22-rdf-syntax-ns#').
rdf_db:ns(mmA,  'http://metamodelA.ecore#').
rdf_db:ns(mmB,  'http://metamodelB.ecore#').
rdf_db:ns(val,  'http://validation.ecore#').
 


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
% LOAD (FOR DEBUGGING ONLY)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


load(File):- rdf_reset_db,rdf_load(File).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% TRANSFORM (+Rules,+OntologyInput,+OntologyOutput)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

transform(_,_,_):-abolish(and/2),abolish((@)/2),fail.

transform(Rules,_,_):-rewrite(Rules,Rules2),[Rules2],fail.

transform(_,_,_):-rdf_reset_db,fail.

transform(_,_,_):-retractall(new(_,_,_)),fail.

transform(_,FileIn,_):-rdf_load(FileIn,[]),fail.

transform(_,_,_):-newrdf(A,B,C),assert(new(A,B,C)),fail.

transform(_,_,_):-rdf_reset_db,fail.

transform(_,_,_):-new(A,B,C),rdf_global_term(B,D),rdf_assert(A,D,C),fail.

transform(_,_,FileOut):-rdf_save(FileOut),rdf_reset_db.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% UPDATE (+Rules,+OntologyInput,+OntologyOutput)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

update(_,_,_):-abolish(and/2),abolish((@)/2),fail.

update(Rules,_,_):-rewrite(Rules,Rules2),[Rules2],fail.

update(_,_,_):-rdf_reset_db,fail.

update(_,_,_):-retractall(new(_,_,_)),fail.

update(_,File,_):-rdf_load(File,[]),fail.

update(_,_,_):-newrdf(A,B,C),assert(new(A,B,C)),fail.

update(_,_,_):-new(A,B,C),rdf_global_term(B,D),rdf_assert(A,D,C),fail.

update(_,_,File):-rdf_save(File),rdf_reset_db.


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% NEWRDF
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

newrdf_head(Head,NA,B,NC):-
			functor(Head,@,2),
			arg(1,Head,Metamodel),
			arg(2,Head,Pred),
			Pred=..[Predic,A,C], 
			rdf_register_ns(Metamodel,URL),
			concat(URL,Predic,B),
			handle(A,NA),handle(C,NC).

newrdf_head(Head,NA,rdf:type,C):-
			functor(Head,@,2),
			arg(1,Head,Metamodel),
			arg(2,Head,Class),
			Class=..[ClassName,A],
			rdf_register_ns(Metamodel,URL),
			concat(URL,ClassName,C),
			handle(A,NA).

newrdf_head(Head,A,B,C):-Head=..[and,First,_],
			 newrdf_head(First,A,B,C).

newrdf_head(Head,A,B,C):-Head=..[and,_,Rest],
			 newrdf_head(Rest,A,B,C).
			 
newrdf(A,B,C):-clause(Head1 and Head2,Cond),
			number_cond(Cond,0,_),
			call_condition(Cond), 
			newrdf_head(Head1 and Head2,A,B,C).


newrdf(NA,B,NC):-clause(Metamodel@Head,Cond),
			Head=..[Pred,A,C],
			rdf_register_ns(Metamodel,URL),
			concat(URL,Pred,B),
			number_cond(Cond,0,_),
			call_condition(Cond),
			handle(A,NA),handle(C,NC).

newrdf(NA,rdf:type,C):-clause(Metamodel@Head,Cond),
				Head=..[Class,A],
				rdf_register_ns(Metamodel,URL),
				concat(URL,Class,C),
				number_cond(Cond,0,_),
				call_condition(Cond),
				handle(A,NA).

%%%%%%%%%%%%%%%
% NUMBER_COND
%%%%%%%%%%%%%%%

number_cond(_,_,_):-retractall(atom_rule(_)),fail.

number_cond(Cond,N,M):-number_cond_aux(Cond,N,M),fail.

number_cond(_,_,_).

number_cond_aux(Cond,N,M):-functor(Cond,@,2),!,numbervars(Cond,num,N,M),assert(atom_rule(Cond)).

number_cond_aux(Cond,N,M):-Cond=..[and,First,Rest],!,number_cond_aux(First,N,K),number_cond_aux(Rest,K,M).

number_cond_aux(Cond,N,M):-numbervars(Cond,num,N,M),assert(atom_rule(Cond)).

%%%%%%%%%%%%%%%%%%%
% CALL CONDITION
%%%%%%%%%%%%%%%%%%%

 

call_condition(Cond):-functor(Cond,@,2),
				arg(1,Cond,Metamodel),
				arg(2,Cond,B),
				B=..[Pred,U,V],!,
				rdf_register_ns(Metamodel,URL),
				concat(URL,Pred,Pred2), 
				rdf(U,Pred2,V).


call_condition(Cond):-functor(Cond,@,2),
				arg(1,Cond,Metamodel),
				arg(2,Cond,B),
				B=..[Class,U],!,
				rdf_register_ns(Metamodel,URL),
				concat(URL,Class,Class2), 
				rdf(U,rdf:type,Class2).

call_condition(Cond):-Cond=..[and,First,Rest],!,
				call_condition(First),
				call_condition(Rest).

call_condition(C):-call(C).

%%%%%%%%%%%%%%%%%%%
% HANDLE
%%%%%%%%%%%%%%%%%%%


 

handle(A,A).

 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FILTER (+Ontology,+Class)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

filter(_,_):-rdf_reset_db,fail.

filter(File,_):-rdf_load(File,[]),fail.

filter(_,_):-retractall(new(_,_,_)),fail.

filter(_,Class):-rdf(A,B,C),rdf(A,rdf:type,Class),assert(new(A,B,C)),fail.

filter(_,Class):-rdf(A,B,C),rdf(C,rdf:type,Class),assert(new(A,B,C)),fail.

filter(_,_):-new(A,B,C),rdf_retractall(A,B,C),fail.

filter(File,_):-rdf_save(File),rdf_reset_db.


%%%%%%%%%%%%%%%%%%%%%%%%%%%
% GENERATE_ID
%%%%%%%%%%%%%%%%%%%%%%%%%%%%

generate_id([Id|RId],IdG):-generate_id2(RId,IdRId),atom_concat(Id,IdRId,IdG).

generate_id2([Object],Object).

generate_id2([Id|RId],IdG):-rdf_split_url(_,Pointer,Id),generate_id2(RId,IdRId),atom_concat(Pointer,IdRId,IdG).

%%%%%%%%%%%%%%%%%%%%%%%
% CONCATSTR
%%%%%%%%%%%%%%%%%%%%%%%%


concatString(literal(type(A,String1)),literal(type(A,String2)),literal(type(A,String3))):-!,concat(String1,String2,String3).

newURI(String1,String2,String3):-concat(String1,String2,String3).


%%%%%%%%%%%%%%%%%%%%%
% EQUAL
%%%%%%%%%%%%%%%%%%%%

equal(A,A).

%%%%%%%%%%%%%%%%%%%%%
% NOTEQUAL
%%%%%%%%%%%%%%%%%%%%

differentFrom(A,B):-A\==B.

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

%%%%%%%%%%%%%%%%%%%
% MAKESET
%%%%%%%%%%%%%%%%%%%

makeSet(_,Set):-atom_rule(makeSet(NVar,_)),search_atom(NVar,New,Atom),setof(New,Atom,Set).

%%%%%%%%%%%%%%%%%%
% SEARCH_ATOM
%%%%%%%%%%%%%%%%%%

search_atom(NVar,New,Atom):-atom_rule(AtomN), 
					functor(AtomN,@,2),
					arg(1,AtomN,Metamodel),
					arg(2,AtomN,Prop),
					Prop=..[Class,NVar],!,
					rdf_register_ns(Metamodel,URL),
					concat(URL,Class,Class2), 
					Atom=rdf(New,rdf:type,Class2).

search_atom(NVar,New,Atom):-atom_rule(AtomN), 
					functor(AtomN,@,2),
					arg(1,AtomN,Metamodel),
					arg(2,AtomN,Prop),
					Prop=..[Pred,_,NVar],!,
					rdf_register_ns(Metamodel,URL),
					concat(URL,Pred,Pred2), 
					Atom=C^rdf(C,Pred2,New).

%%%%%%%%%%%
% ELEMENT
%%%%%%%%%%%

element(A,L):-member(A,L).

%%%%%%%%%%%%%
% NOTELEMENT
%%%%%%%%%%%%%

notElement(A,L):-  \+ member(A,L).
 
%%%%%%%%%%%%%%%%%%%%%
% REWRITE
%%%%%%%%%%%%%%%%%%

rewrite(File,File2):-open(File,read,Stream),concat('OTL',File,File2),
		open(File2,write,Stream2),
		rewrite_file(Stream,Stream2),
		close(Stream2),
		close(Stream).

rewrite_file(Stream,_):-at_end_of_stream(Stream),!.
rewrite_file(Stream,Stream2):-
		get_char(Stream,C), 
		 
		 
		(C=':'->(
			 get_char(Stream,D),
			 (D='-'->
			 (put(Stream2,C),put(Stream2,D));	
			 (D=':'->
			 put(Stream2,'&');
			 put(Stream2,'@'),put(Stream2,D))) 
			 );
			 
			
		put(Stream2,C) 
		),
		rewrite_file(Stream,Stream2).