%
% query to XML translating module
% MUST NOT consult this one but cif2xml
%
% K. Hui 07/05/2002
%


%
% query RDFS URL
%
:- retractall(cif2xml:url(query_rdfs,_)).
:- assertz(cif2xml:url(query_rdfs,'http://www.csd.abdn.ac.uk/~khui/akt/cif/cif-query-rdfs.xml')).

%
% assuming that a query takes the form of query/2
% where the 1st argument is a list of variables
% & the 2nd argument is a list of generators + filters
%
query2xml(Params,Query,Xml) :-
	var(Xml),
	url(rdf,Rdf_url),
	concat_atoms:add_prefix(Rdf_url,'#',Rdf_url_with_hash),
	url(rdfs,Rdfs_url),
	concat_atoms:add_prefix(Rdfs_url,'#',Rdfs_url_with_hash),
	member(representation=Rep,Params),
	match_rdfs_url(Rep,Cif_url),
	concat_atoms:add_prefix(Cif_url,'#',Cif_url_with_hash),
	url(query_rdfs,Daplex_url),
	concat_atoms:add_prefix(Daplex_url,'#',Daplex_url_with_hash),
	Attribs=[	'xmlns:rdf'=Rdf_url_with_hash,
			'xmlns:rdfs'=Rdfs_url_with_hash,
			'xmlns:cif'=Cif_url_with_hash,
			'xmlns:daplex'=Daplex_url_with_hash
		],
	Xml=[X_decl,X_rdf],
	X_decl=xmldecl([version='1.0']),
	X_rdf=env('rdf:RDF',Attribs,X_query),
	query2xml_query(Params,[],Query,_,_,X_query),		%start w/ no known ID
	!.

%
% XML -> CIF
%
query2xml(Params,Cif,Xml) :-
	nonvar(Xml),
	X_decl=xmldecl([version='1.0']),			%XML declaration
	X_rdf=env('rdf:RDF',_,X_query),				%RDF content
	member(X_decl,Xml),					%match XML declaration
	member(X_rdf,Xml),					%match RDF subtree
	query2xml_query(Params,[],Cif,_,_,X_query).		%start w/ no known ID

%
% query
%
% CIF -> XML
%
query2xml_query(Params,Known,Query,New_params,New_known,Xml) :-
	var(Xml),
	Query=query(Variables,Zf),					%query in the form query/2
	Xml=env('daplex:query',[],X_list),		%daplex:query
	X_query_body=env('daplex:query_body',[],X_zf_expr),		%daplex:query_body
	query2xml_wanted(Params,Known,Variables,Temp_params,Temp_known,X_wanted),	%get list of cif:variable
%	sort_zf(Zf,Sorted_zf),									%sort list according tot dependency
	Zf=Sorted_zf,
	query2xml_zf_expr(Temp_params,Temp_known,Sorted_zf,New_params,New_known,X_zf_expr),	%get daplex:zf_expr
	my_append(X_wanted,X_query_body,X_list).

query2xml_query(Params,Known,Query,New_params,New_known,Xml) :-
	nonvar(Xml),
	Query=query(Variables,Zf),					%query in the form query/2
	Xml=env('daplex:query',_,X_list),				%daplex:query
	X_wanted_template=env('daplex:query_wanted',_,_),		%daplex:quer_wanted template
	X_query_body=env('daplex:query_body',_,X_zf_expr),		%daplex:query_body template
	findall(X_wanted_template,member(X_wanted_template,X_list),X_wanted),			%match all daplex:query_wanted
	member(X_query_body,X_list),					%match daplex:query_body
	query2xml_wanted(Params,Known,Variables,Temp_params,Temp_known,X_wanted),	%get list of cif:variable
%	sort_zf(Zf,Sorted_zf),									%sort list according tot dependency
	Zf=Sorted_zf,
	query2xml_zf_expr(Temp_params,Temp_known,Sorted_zf,New_params,New_known,X_zf_expr).	%get daplex:zf_expr


%
% map a list of variables <-> XML
%
query2xml_wanted(Params,Known,[],Params,Known,[]).
query2xml_wanted(Params,Known,[V|Vs],New_params,New_known,[X|Xs]) :-
	X=env('daplex:query_wanted',[],[X_variable]),
	cif2xml_variable(Params,Known,V,Temp_params,Temp_known,X_variable),
	query2xml_wanted(Temp_params,Temp_known,Vs,New_params,New_known,Xs).

%
% ZF expression
%
% CIF -> XML
%
query2xml_zf_expr(Params,Known,Cif,New_params,New_known,Xml) :-
	var(Xml),								%CIF -> XML
	Xml=env('daplex:zf_expr',[],X_list),					%daplex:zf_expr
	X_generator=env('daplex:zf_expr_generator',[],[X_setmem]),		%daplex:zf_expr_generator
	%
	% take 1st generator from list
	%
	Cif=[Gen|Others],							%get generator in the front
	%
	% find which variable it generates
	%
	Patterns=[generate(_,Var),generate(_,_,_,_,Var)],			%pattern that matches generate/2 & generate/5
	member(Gen,Patterns),							%Cif is a generate/2 or /5
	%
	% map generator of this var into cif:setmem
	%
	cif2xml_generator(Params,Known,gen(Var,[Gen]),Temp_params1,Temp_known1,X_setmem),	%get cif:setmem
	%
	% now get extra condition on this variable as such-that
	% we have to focus on non-gen as this variable may be used
	% to generate other variables (by generate/5)
	%
	Gen_patterns=[generate(_,_),generate(_,_,_,_,_)],			%pattern that matches generate/2 & generate/5
	match_pattern(Others,Gen_patterns,Others_gen,Others_non_gen),		%split remaining CIF into gen & non-gen
	%
	% now find CIF about this variables, but not generators
	%
	cif_util:cif_about_var(Var,Others_non_gen,Suchthat,Non_gen_remain),	%find CIF about this var, excluding the generate/2 or /5
	%
	% if such-that is not empty, map it into a boolpred
	%
	(	(	Suchthat=[],
			!,
			Temp_params1=Temp_params2,
			Temp_known1=Temp_known2,
			Temp_x_list=[X_generator]
		);
		(	cif2xml_boolpred(Temp_params1,Temp_known1,Suchthat,Temp_params2,Temp_known2,X_boolpred),	%get cif:boolpred
			X_filter=env('daplex:zf_expr_filter',[],[X_boolpred]),				%daplex:zf_expr_filter
			Temp_x_list=[X_generator,X_filter]
		)
	),
	%
	% now remaining is other gens + non-gen-remain
	%
	append_cif(Others_gen,Non_gen_remain,Remain),
	(	(	Remain=[],						%no nested query
			!,
			New_params=Temp_params2,
			New_known=Temp_known2,
			X_list=Temp_x_list
		);
		(	X_nested=env('daplex:zf_expr_nested',[],[X_zf_expr_nested]),				%daplex:zf_expr_nested
			query2xml_zf_expr(Params,Temp_known2,Remain,New_params,New_known,X_zf_expr_nested),	%get nested daplex:zf_expr
			append(Temp_x_list,[X_nested],X_list)
		)
	),
	!.

%
% XML -> CIF
%
query2xml_zf_expr(Params,Known,Cif,New_params,New_known,Xml) :-
	nonvar(Xml),											%XML -> CIF
	Xml=env('daplex:zf_expr',[],X_list),								%match daplex:zf_expr
	X_generator=env('daplex:zf_expr_generator',[],[X_setmem]),					%daplex:zf_expr_generator template
	X_filter=env('daplex:zf_expr_filter',[],[X_boolpred]),						%daplex:zf_expr_filter template
	X_nested=env('daplex:zf_expr_nested',[],[X_zf_expr_nested]),					%daplex:zf_expr_nested template
	member(X_generator,X_list),									%match daplex:generator
	cif2xml_generator(Params,Known,gen(_,Gen),Temp_params1,Temp_known1,X_setmem),			%get generator from cif:setmem
	%
	% optional daplex:query_filter
	%
	(	(	member(X_filter,X_list),									%match daplex:filter
			!,
			cif2xml_boolpred(Temp_params1,Temp_known1,Suchthat,Temp_params2,Temp_known2,X_boolpred)		%get suchthat from cif:boolpred
		);
		(	Temp_params1=Temp_params2,
			Temp_known1=Temp_known2,
			Suchthat=[]
		)
	),
	append_cif(Gen,Suchthat,Temp_cif),
	%
	% optional daplex:query_zf_expr_nested
	%
	(	(	member(X_nested,X_list),							%if nested ZF expr exist
			!,
			query2xml_zf_expr(Params,Temp_known2,Remain,New_params,New_known,X_zf_expr_nested),
			append_cif(Temp_cif,Remain,Cif)
		);
		(	Cif=Temp_cif,
			New_params=Temp_params2,
			New_known=Temp_known2
		)
	),
	!.



%
% query result to XML mapping
%
% CIF -> XML
%
result2xml(Params,Cif,Xml) :-
	var(Xml),
	url(rdf,Rdf_url),
	concat_atoms:add_prefix(Rdf_url,'#',Rdf_url_with_hash),
	url(rdfs,Rdfs_url),
	concat_atoms:add_prefix(Rdfs_url,'#',Rdfs_url_with_hash),
	member(representation=Rep,Params),
	match_rdfs_url(Rep,Cif_url),
	concat_atoms:add_prefix(Cif_url,'#',Cif_url_with_hash),
	url(query_rdfs,Daplex_url),
	concat_atoms:add_prefix(Daplex_url,'#',Daplex_url_with_hash),
	Attribs=[	'xmlns:rdf'=Rdf_url_with_hash,
			'xmlns:rdfs'=Rdfs_url_with_hash,
			'xmlns:cif'=Cif_url_with_hash,
			'xmlns:daplex'=Daplex_url_with_hash
		],
	Xml=[X_decl,X_rdf],
	X_decl=xmldecl([version='1.0']),
	X_rdf=env('rdf:RDF',Attribs,X_result),
	result2xml_result(Params,[],Cif,_,_,X_result),		%start w/ no known ID
	!.

%
% XML -> CIF
%
result2xml(Params,Cif,Xml) :-
	nonvar(Xml),
	X_decl=xmldecl([version='1.0']),			%XML declaration
	X_rdf=env('rdf:RDF',_,X_result),			%RDF content
	member(X_decl,Xml),					%match XML declaration
	member(X_rdf,Xml),					%match RDF subtree
	result2xml_result(Params,[],Cif,_,_,X_result).		%start w/ no known ID

%
% CIF <-> XML
%
result2xml_result(Params,Known,Cif,New_params,New_known,Xml) :-
	Cif=result(tuples(Tuples)),
	Xml=env('daplex:query_result',[],X_tuples),
	result2xml_tuples(Params,Known,Tuples,New_params,New_known,X_tuples).

%
% a list of tuples
%
result2xml_tuples(Params,Known,[],Params,Known,[]).
result2xml_tuples(Params,Known,[T|Ts],New_params,New_known,[X|Xs]) :-
	X=env('daplex:query_result_has_tuple',[],[X_tuple]),
	X_tuple=env('daplex:tuple',[],X_tuple_assignments),
	result2xml_tuple(Params,Known,T,Temp_params,Temp_known,X_tuple_assignments),
	result2xml_tuples(Temp_params,Temp_known,Ts,New_params,New_known,Xs).

%
% one single tuple
%
result2xml_tuple(Params,Known,[],Params,Known,[]).
result2xml_tuple(Params,Known,[Var=Value|As],New_params,New_known,[X|Xs]) :-
	X=env('daplex:tuple_has_assignment',[],[X_assignment]),
	X_assignment=env('daplex:value_assignment',[],[X_assignment_var,X_assignment_value]),
	X_assignment_var=env('daplex:value_assignment_var',[],[X_variable]),
	X_assignment_value=env('daplex:value_assignment_value',[],[X_constant]),
	cif2xml_variable(Params,Known,Var,Temp_params1,Temp_known1,X_variable),
	cif2xml_constant(Temp_params1,Temp_known1,Value,Temp_params2,Temp_known2,X_constant),
	result2xml_tuple(Temp_params2,Temp_known2,As,New_params,New_known,Xs).

