:-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).