:-eval(consult("utils.prova")).

:- eval(uniprot()).

location(database,uniprot,"jdbc:mysql://localhost/uniprot","username","password").

uniprot() :-
	println(["==========uniprot parser=========="]),
	File="uniprot_sprot.xml",
	dbopen(uniprot,DB),
	fopen(File,Reader),
	I=java.util.ArrayList(),
	I.add(0),
	rec(DB,I,Reader).

rec(DB,I,Reader) :-
	Line=Reader.readLine(),
	rec2(DB,I,Reader,Line).

rec2(DB,I,Reader,Line) :-
	Entry=StringBuffer(),
	process_0(Reader,Entry,Line),
	processEntry(DB,I,Entry).
rec2(DB,I,Reader,Line) :-
	rec(DB,I,Reader).

process_0(Reader,Entry,Line) :-
	Line.startsWith("<entry"),
	process_1(Reader,Entry,Line).

process_1(Reader,Entry,Line) :-
	Line.startsWith("</entry"),
	Entry.append(Line),
	!.
process_1(Reader,Entry,Line) :-
	Entry.append(Line),
	Line2=Reader.readLine(),
	process_1(Reader,Entry,Line2).

% Individual UniProt entry
processEntry(DB,I,Entry) :-
	StringEntry=Entry.toString(),
	SR=java.io.StringReader(StringEntry),
	Doc=XML(SR),
	Root=Doc.getDocumentElement(),
	Names=java.util.ArrayList(),
	processChildren(Names,Root),
	ArrNames=Names.toArray(),
	Ids=java.util.ArrayList(),
	insertNames(DB,I,ArrNames,Ids),
	processNames(DB,Ids).

processNames(DB,Ids) :-
	ArrayIds=Ids.toArray(),
	pair(P,ArrayIds),
	insertPair(DB,P),
	fail().
processNames(DB,Ids).

% Process each child of the current Element and add the appropriate pairs
%   (Term,Type) accordingly
processChildren(List,Element) :-
	Els = Element.getChildNodes(),
	Els.nodes(El),
	Tag = El.getNodeName(),
	processTag(Tag,List,El),
	fail().
processChildren(List,Element).

processTag(Tag,List,Element) :-
	member(Tag,[accession,name]),
	DataName = Element.getFirstChild(),
	StringName = DataName.getNodeValue(),
	Res=java.util.ArrayList(),
	Res.add(StringName),
	Res.add(Tag),
	List.add(Res).
processTag(Tag,List,Element) :-
	member(Tag,[protein,gene]),
	Els = Element.getChildNodes(),
	Els.nodes(El),
	ChildTag = El.getNodeName(),
	ChildTag = name,
	DataName = El.getFirstChild(),
	StringName = DataName.getNodeValue(),
	Res=java.util.ArrayList(),
	Res.add(StringName),
	Res.add(Tag),
	List.add(Res).

insertNames(DB,I,ArrNames,Ids) :-
	member(A,ArrNames),
	I0=I.get(0),
	Name=A.get(0),
	Type=A.get(1),
	Ids.add(I0),
println(["Term:",I0,[Name,Type]]," "),
	sql_insert(DB,term,[name,type],[Name,Type]),
	I1=I0+1,
	I.set(0,I1),
	fail().
insertNames(DB,I,ArrNames,Ids).

insertPair(DB,[ID1,ID2]) :-
%println([ID1,ID2]," ").
	sql_insert(DB,synonym,[id1,id2],[ID1,ID2]).

% XML DOM helper predicate
getFirstElementText(Element,Tag,Out) :-
	Els = Element.getElementsByTagName(Tag),
	Els.nodes(El),
	DataName = El.getFirstChild(),
	Out = DataName.getNodeValue(),
	!.

% General helper predicates
member(X,[X|Xs]).
member(X,[_|Xs]) :-
	member(X,Xs).

% The first argument holds an ordered pair from the list in the second argument  
% To test run > :- solve(pair(Z,[1,2,3,4])).
pair(P,[X|Xs]) :-
	pair1(P,X,Xs).
pair(P,[X|Xs]) :-
	pair(P,Xs).

pair1(P,X,[Y|Ys]) :-
	pair2(P,X,Y).
pair1(P,X,[_|Ys]) :-
	pair1(P,X,Ys).

pair2([X,Y],X,Y).
pair2([Y,X],X,Y).

