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