import org.jibble.pircbot.*;
import org.ilrt.inkling.api.*;
import org.ilrt.inkling.query.*;
import org.ilrt.inkling.query.squish.*;
import java.util.*;
import com.ibm.icu.text.Normalizer;
import com.ibm.icu.text.Transliterator;

public class TestBot extends PircBot {
    
    public TestBot() {
        this.setName("wh4experimental");

	oldcommands.put("!source","looks for sources contaiing this string");
	oldcommands.put("!iata","search by iata code for names of airports");
	oldcommands.put("!airport","search for airports by name of town");
	oldcommands.put("!foaf:","search for foaf properties of the specified person by name e.g. foaf:nick");
	oldcommands.put("!pic","looks for images of the specified person");
	oldcommands.put("!put","adds url to the database");
	oldcommands.put("!remove","removes url from the database");
	oldcommands.put("!info","ask for info by command");
	oldcommands.put("!bye","makes the bot leave the server");
	oldcommands.put("!help","gives a list of commands");

	readCommands(filename);

    }

//the first url to look for info
String 
url="http://swordfish.rdfweb.org/discovery/2004/05/wh4/rdfxmlquery.jsp?query=";

Hashtable cache = new Hashtable();
static Hashtable commands = new Hashtable();
static Hashtable oldcommands = new Hashtable();

String commandstxt="";
String filename="file:commands.rdf";


    public static void main(String[] args) throws Exception {

        
        // Now start our bot up.
        TestBot bot = new TestBot();
	bot.setEncoding("UTF-8");

        // Enable debugging output.
        bot.setVerbose(false);
        
        // Connect to the IRC server.
        bot.connect("irc.freenode.net");

        // Join the channel.
        bot.joinChannel("#whwhwhwh");
        bot.joinChannel("#foaf");
        bot.joinChannel("#rdfig");
        bot.joinChannel("#swhack");


	bot.commandstxt=bot.getCommands(bot.commandstxt);

    }
    
    public void onPrivateMessage(String sender, String login, String
hostname, String message) {

	onMessage(sender,sender,login,hostname,message);


    }

    public void onMessage(String channel, String sender,
                       String login, String hostname, String message) {



	        if (message.startsWith("!pic ")) {
		getPicsByName(message,channel);
		}

                if (message.startsWith("!foaf:")) {
                getFoafData(message,channel);
                }

                if (message.startsWith("!airport ")) {
                getAirportsByLocation(message,channel);
                }


                if (message.startsWith("!iata ")) {
                getAirportsByIata(message,channel);
                }

                if (message.startsWith("!put ")) {
                puturl(message,channel);
                }

                if (message.startsWith("!source ")) {
                getSource(message,channel);
                }

                if (message.startsWith("!remove ")) {
                removeurl(message,channel);
                }

//experiment: telling the botnew queries and their shortcuts

		if(message.startsWith("wh4, new shortcut")){
		newShortcut(message,channel);
		}


                if (message.startsWith("!remove ")) {
//??		oldcommands.put("!remove ");
                removeurl(message,channel);
                }

	        if (message.startsWith("wh4, help")
		| (message.startsWith("!help"))) {
		help(channel);
		}

	        if (message.startsWith("!info")) {
		getInfo(message,channel);
		}

	        if (message.startsWith("!bye")) {
//		oldcommands.addElement("!bye");
		quitServer("I..know...EVERYTHING!!!");
		System.exit(1);
		}

		if(message.startsWith("!")){

//		check commands hash
		String msg=message;
			if(message.indexOf(" ")!=-1){
			msg=message.substring(0,message.indexOf(" "));
			}else{
			msg.trim();
			}

//			System.out.println("OC
//"+oldcommands.toString());
			if(msg.equals("!")){

			}//nothing
			else{

			if(!oldcommands.contains(msg)){

//			sm(channel,"checking commands database");		

				if(commands.containsKey(msg)){
		//		sm(channel,"found a command "+msg);
	//			sm(channel,"found a command
//"+(String)commands.get(msg));

				getTemplatedQuery(message,(String)commands.get(msg),channel);
				}else{

//				sm(channel,"no command found. Commands are: "+commandstxt);

				}
			}

			}
	
		}


    }


/**

help

*/

   public void help(String channel){

	sm(channel,"I'm a very experimental RDF-webservice-based bot by libby.miller@bristol.ac.uk, based on the pircbot api. More info at http://swordfish.rdfweb.org/discovery/2003/10/whwhwhwh/");
sm(channel, "commands are: "+commandstxt+". You can tell it more like "+
"this: 'wh4, new shortcut !bla is select ?ble where (somepredicate "+
"?something ?ble) and ?ble ~ '$1' ' (any squish rdf query with a "+
"predicate in each clause).");
 }



/**

better version - muliple people, plus places and things

something like: !pic <name>, and <name>, a <thing>, at <place>, on <date>

*/


public void getPicsByName(String message,String channel){

int limit=4;
Vector v = Util.splitByString(message, ",");

Vector names= new Vector();
Vector things= new Vector();
String place=null;
String date=null;

Enumeration e = v.elements();
int i=0;
	while(e.hasMoreElements()){

	String part = (String)e.nextElement();

//System.out.println("part "+part);

		if(i==0){

		part=part.substring(5).trim();

		}

			if(part.startsWith("and ")){
			names.addElement(part.substring(4).trim());
			}
			else if(part.startsWith("a ")){
			things.addElement(part.substring(2).trim());
			}
			else if(part.startsWith("the ")){
			things.addElement(part.substring(4).trim());
			}
			else if(part.startsWith("some ")){
			things.addElement(part.substring(5).trim());
			}
			else if(part.startsWith("at ")){
			place=part.substring(3).trim();
			}
			else if(part.startsWith("near ")){
			place=part.substring(5).trim();
			}
			else if(part.startsWith("in ")){
			place=part.substring(3).trim();
			}
			else if(part.startsWith("on ")){
			date=part.substring(3).trim();
			}else{
			names.addElement(part);//??
			}

//		}
	
	i++;

	}


String q=null;

//create the query

String sq="select ?pic,";

for (int j=0;j<names.size();j++){

	sq=sq+" ?name"+j+",";
}


if(place!=null){
sq=sq+" ?place,";
}
if(date!=null){
sq=sq+" ?dat,";
}

sq=sq.trim();

System.out.println("sq is "+sq+"....");

if(sq.endsWith(",")){
sq=sq.substring(0,sq.length()-1);
}

sq=sq+" where ";

for (int k=0;k<names.size();k++){
sq=sq+" (foaf:depicts ?pic ?person"+k+") ";
sq=sq+" (foaf:name ?person"+k+" ?name"+k+") ";
//sq=sq+" (foaf:depiction ?person"+k+" ?pic) ";
//sq=sq+" (foaf:name ?person"+k+" ?name"+k+") ";
}

String wn="http://xmlns.com/wordnet/1.6/";
if(things.size()>0){
	for (int k=0;k<things.size();k++){
	String thingy=(String)things.elementAt(k);

	thingy=thingy.substring(0,1).toUpperCase()+thingy.substring(1).toLowerCase();

	String type=wn+thingy;
	sq=sq+" (foaf:depicts ?pic ?thing"+k+") ";
	sq=sq+" (rdf:type ?thing"+k+" "+type+") ";	
	}
}


if(place!=null){
sq=sq+" (foaf:creationEvent ?pic ?event) (contact:nearestAirport ?event "+
"?airport) (doa:location ?airport ?place) ";
}

if(date!=null){
sq=sq+" (foaf:creationEvent ?pic ?event) (ical:date ?event ?dat) ";
}



for (int l=0;l<names.size();l++){
String name=(String)names.elementAt(l);
if(name.trim().equals("*")){
}else{
sq=sq+" and ?name"+l+" ~ '"+name+"' ";
}
}
if(place!=null){
sq=sq+" and ?place"+" ~ '"+place+"' ";
}

if(date!=null){
sq=sq+" and ?dat"+" ~ '"+date+"' ";
}

sq=sq+" using foaf for http://xmlns.com/foaf/0.1/ rdfs for "+
"http://www.w3.org/2000/01/rdf-schema# rdf for "+
"http://www.w3.org/1999/02/22-rdf-syntax-ns# "+
"contact for http://www.w3.org/2000/10/swap/pim/contact# "+
"ical for http://www.w3.org/2002/12/cal/ical# "+
"doa for http://www.daml.org/2001/10/html/airport-ont#";

//String 
//url="http://swordfish.rdfweb.org/discovery/2001/08/codepict/rdfxmlquery.jsp?query="+java.net.URLEncoder.encode(sq);


	getRDF(url,sq,null,channel,limit);

//	sm(channel,"query was "+sq);


}




///something like....

//first try wh4 one; then try others. cache queries and locations
//i.e. try
//http://swordfish.rdfweb.org/discovery/2004/05/wh4/rdfxmlquery.jsp
//->more results
//try thesein turn
//e.g
//http://swordfish.rdfweb.org/discovery/2001/08/codepict/rdfxmlquery.jsp
//etc

//todo: caching
///most important - how do we tell the db about new sources?

/**

Get RDF from a url using a remote source and then query it using a
squish query and write back to the channel.

*/

    public void getRDF(String url, String q, String channel){

	getRDF(url,q,null,channel,-1);
    }

    public void getRDF(String url, String q, String keywordq,String channel, int limit){

//check the cache first
	String querysummary=sortQuery(q);
	Vector subcache=(Vector)cache.get(querysummary);

/*
		if(subcache!=null && subcache.size()>0){
			if(subcache.contains(url)){
			//all ok
			}else{
			//replace it
//removed caching    
			url=(String)subcache.elementAt(0);
//			sm(channel,"USING CACHE "+url);
			}
		}

*/
	Graph g = null;

//keyowrd q is for things which dont need a full squish query

		if(keywordq!=null && (!keywordq.equals(""))){
		g=new Graph(url+""+java.net.URLEncoder.encode(keywordq),Util.RDFXML);
		}else{
		g=new Graph(url+""+java.net.URLEncoder.encode(q),Util.RDFXML);
		}

	//g = new Graph(url+""+java.net.URLEncoder.encode(q),Util.RDFXML);

	if(q!=null && (!q.equals(""))){

	int count=0;
	if(limit==-1){
	limit=count;
	}

		try{

		g.load();

///first see if we need to look elsewhere

		Vector vec=g.ask(null,"http://example.com/routertest#couldBeAnsweredBy",null);
		//here also ask about the type of query@@
		//e.g. keyword & pred


//this vec tells us where to find stuff related to this query
//want to store this info somewhere
//2 diff sorts of things. one is the raw preds, other is processed
//second is what interested in
//what we'd like to have is a list of queries (sorted preds,
//effectively) mapped to places to get them
//indexed by the query not the source
///many to many....hashtable wont do....hash of vectors
//sorting algo for queries? (sort)

		int chosen=0;
		String newurl=url;

		for (int i=0; i<vec.size(); i++){
			if(vec.size()>0){
			//reload the graph with first new url
			//and loop through rest if nothing found
			//also need to cache@@
			Statement st = (Statement)vec.elementAt(i);
			newurl=st.getObject().getContent();

System.out.println("!!!!!!!!"+keywordq);

			if(keywordq!=null && (!keywordq.equals(""))){
			g=new Graph(newurl+""+java.net.URLEncoder.encode(keywordq),Util.RDFXML);
			}else{
			g=new Graph(newurl+""+java.net.URLEncoder.encode(q),Util.RDFXML);
			}
			g.load();
			Vector vec2=g.ask(null,"http://example.com/routertest#couldBeAnsweredBy",null);
				if(vec2.size()==0 && g.size()>0){
				chosen=i;
				break;
				}
			}
		}



		
		java.sql.ResultSet r=g.askSquish(q);
		while(r.next()){

		if(count<=limit){
		count++;
//		StringBuffer sb = new StringBuffer();

		String sb="";
			Vector v=((org.ilrt.inkling.query.ResultSet)r).getColumnNames();
			Enumeration e=v.elements();
			while(e.hasMoreElements()){
			String var=(String)e.nextElement();
//			sb.append((String)r.getString(var)+" ");
			String gg=(String)r.getString(var);
			//System.out.println(gg);
			sb=sb+gg+" ";
			}

			if(!sb.trim().equals("")){
			sm(channel," "+sb);
			}


		}

		}

		if(count==0){
			sm(channel,"no results found, sorry");
///here try other places
//for now just remove from cache
//if it's not in the cache put it there
/*
			if(subcache!=null && subcache.size()>0){

                        Statement st = (Statement)vec.elementAt(chosen);
                        String newurl=st.getObject().getContent();

			subcache.removeElement(newurl);
			sm(channel, "removing "+newurl+" cache is now "+cache.toString());
			}
*/
		}else{

			if(subcache==null){
			subcache=new Vector();
			cache.put(querysummary,subcache);
			}

/*
//			for (int i=0; i<vec.size(); i++){
//			Statement st = (Statement)vec.elementAt(i);
//			String newurl=st.getObject().getContent();
				if(!subcache.contains(newurl)){
				subcache.addElement(newurl);
				sm(channel,"adding to cache "+newurl);
				}
//			}
*/

		}

		}catch(Exception e){
		System.err.println(e);
		e.printStackTrace();
		sm(channel,"nothing found");
		}


	}

    }


public void sm(String channel,String msg) {

String enc="";

   try{
        enc=getEncoding();
   }catch(Exception e){
        enc="UTF-8";
   }

        if(enc.equals("UTF-8")){
        sendMessage(channel,msg);
        }else{

                try{
                String normmsg=Normalizer.normalize(msg,Normalizer.DEFAULT);
                String normmsg2=new String(normmsg.getBytes(enc));
                sendMessage(channel,normmsg2);

                }catch(Exception ez){
                sendMessage(channel,msg);
                }
        }
   
}


public String sortQuery(String query){

ComplexQuery cq=(ComplexQuery)SquishParser.parse(query);
Vector triples=cq.getTriples();
Vector querypredlist=new Vector();
Enumeration e = triples.elements();

	while(e.hasMoreElements()){
	Statement s = (Statement)e.nextElement();
	querypredlist.addElement(s.getPredicate().getContent());
	}


        if(querypredlist.size() == 0) {
            return null;
        }

        Collections.sort(querypredlist,new Comparator() {
                
            public int compare(Object o1, Object o2) {
                int i = o1.toString().compareTo(o2.toString());
                return i;
            }
        }); 

StringBuffer preds=new StringBuffer();
Enumeration en = querypredlist.elements();

	for (int i=0; i<querypredlist.size();i++){
//	System.out.println("list "+o);
	preds.append(" "+querypredlist.elementAt(i));
	}

System.out.println("preds are "+querypredlist.size());
System.out.println("PREDS "+querypredlist.toString());

return preds.toString();


}

/**

get any foaf term with domain Person or agent where you expect a name to
also be present
                 
*/                       
                
                
public void getFoafData(String message, String channel){
                
                 
boolean bynick=false;   
//System.out.println(message+"[1]");
     
int z=message.indexOf("by nick");
if (z!=-1){
bynick=true;
message=message.substring(0,z)+message.substring(z+7);
}

                 
int i=message.indexOf(" ");
int j=message.indexOf(":");
String q=null;  
String f=null;
                
        if(i!=-1 && j!=-1){

        q=message.substring(i+1).trim();
        f=message.substring(j+1,i).trim();
     


String sq="";

if(f.equals("name")){

        if(bynick){
        sq="select ?name, ?nick where "+
        " (foaf:name ?per ?name) "+
        " (foaf:nick ?per ?nick) "+
        " and ?nick ~ '"+q+"' ";
        }else{  
        sq="select ?name where "+
        " (foaf:name ?per ?name) "+
        " and ?name ~ '"+q+"' ";
        }
        sq=sq+" using foaf for http://xmlns.com/foaf/0.1/";

}else{

        sq="select ?foafterm, ?name where "+
        " (foaf:"+f+" ?per ?foafterm) ";

        if(bynick){
        sq=sq+" (foaf:nick ?per ?name) "+
        " and ?name ~ '"+q+"' ";
        }else{  
        sq=sq+" (foaf:name ?per ?name) "+
        " and ?name ~ '"+q+"' ";
        }
        sq=sq+" using foaf for http://xmlns.com/foaf/0.1/";
}
        
/*
        String
url="http://swordfish.rdfweb.org/discovery/2001/08/codepict/rdfxmlq
uery.jsp?query="+java.net.URLEncoder.encode(sq);
*/

        if(!f.equals("mbox")){
///fixme - ailto etc

        getRDF(url,sq,null,channel,10);
        
        }
        
        }else{
        sm(channel,"try e.g. !foaf:weblog <name> to find weblogs of people");
        }
        
}//end foaf method


/**

chump search

*/
/*

public void getChumpUrl(String message,String channel){

int limit=5;
int i=message.indexOf(" ");
String q=null;
boolean substr=false;

        if(i!=-1){
        q=message.substring(i+1);
        if(q.trim().startsWith("~")){
        q=q.substring(1);
        substr=true;
        }

        String
url="http://swordfish.rdfweb.org/discovery/2001/04/rdfig/byurlrdfxml.jsp?urlexa$

        if(substr){
url="http://swordfish.rdfweb.org/discovery/2001/04/rdfig/byurlrdfxml.js$
        }   

String sq="";
        if(substr){  
        sq="select ?url where "+
        " (chump:link ?url ?chumplink) ";
        }else{
        sq="select ?chumplink where "+
        " (chump:link ?url ?chumplink) ";
        }
         
        sq=sq+" using rss for http://purl.org/rss/1.0/ "+
        " chump for http://usefulinc.com/ns/chump#";

        getRDF(url,sq,channel,limit);
        
        }else{
        sm(channel,"try !chump <url> to see if and when a url has been "+
"chumped before on #rdfig. .chump uses an exact match.");

        }
         
        
}

*/

/**

add a url to own database

*/


public void puturl(String message, String channel){

int i=message.indexOf(" ");
String uri=null;
        
        if(i!=-1){
        uri=message.substring(i+1).trim();

	String db="jdbc:mysql://127.0.0.1:3306/wh4?user=mysql&useUnicode=true&characterEncoding=utf-8";

        SQLGraph s = new SQLGraph();
        s.setdb(db);
        s.setDriver("com.mysql.jdbc.Driver");
        
        Graph g = new Graph(null,uri,Util.RDFXML);
        g.load();
        
	sm(channel,"ok, that might take a few seconds");
        s.add(g);
	sm(channel,"added datasource description "+uri);

	}else{
        sm(channel,"try !put <url> to tell the db about a datasource."+
" url should contain a list of predicates the db knows about, e.g http://swordfish.rdfweb.org/discovery/2001/08/codepict/rdfxmlquery.jsp?getpreds=anything");
	}

}



public void removeurl(String message, String channel){

int i=message.indexOf(" ");
String uri=null;
        
        if(i!=-1){
        uri=message.substring(i+1).trim();

	String db="jdbc:mysql://127.0.0.1:3306/wh4?user=mysql&useUnicode=true&characterEncoding=utf-8";

        SQLGraph s = new SQLGraph();
        s.setdb(db);
        s.setDriver("com.mysql.jdbc.Driver");
        
	sm(channel,"ok, that might take a few seconds");
        s.remove(uri);
	sm(channel,"removed datasource description "+uri);

///@@fixme

	cache=new Hashtable();

	}else{
        sm(channel,"try !remove <url> to remove triples from a url from the database");
	}

}




/**

Takes a message and then searches the remote data base by string for
airports, finding lat/long, location and country

*/
                
public void getAirportsByLocation(String message, String channel){
                 
int i=message.indexOf(" ");
String q=null;
        if(i!=-1){
        q=message.substring(i+1);

//        String
//url="http://swordfish.rdfweb.org/discovery/2003/06/airports/xmlrdf.jsp?query="+$

        String sq="select ?loc, ?la, ?lo, ?co, ?iata where "+
        " (air:location ?airport ?loc) "+
        " (pos:lat ?airport ?la) "+
        " (pos:long ?airport ?lo) "+
        " (air:iataCode ?airport ?iata) "+
        " (vcard:country ?airport ?co) "+
        " using air for http://www.daml.org/2001/10/html/airport-ont# "+
        " pos for http://www.w3.org/2003/01/geo/wgs84_pos# "+
        " vcard for http://www.w3.org/vcard-rdf/3.0# ";

        getRDF(url,sq,q,channel,10);
         
        }else{
        sm(channel,"try !airport bristol to find airports near Bristol");
        }


}


/**

similar to above but search by iata code
        
note: this will not work at present.
it thinks it can use my db but a single query won't work (it wants
location@@)

*/


public void getAirportsByIata(String message,String channel){
        
int i=message.indexOf(" ");
String q=null;
        if(i!=-1){q=message.substring(i+1);
///        String url="http://jibbering.com/rdf/airports.1?"+q;
///later
        String sq="select ?loc, ?la, ?lo where "+
        " (air:location ?airport ?loc) "+
        " (pos:lat ?airport ?la) "+
        " (pos:long ?airport ?lo) "+
        " using air for http://www.daml.org/2001/10/html/airport-ont# "+
        " pos for http://www.w3.org/2003/01/geo/wgs84_pos# "+
        " vcard for http://www.w3.org/vcard-rdf/3.0# ";
  
//        getRDF(url,sq,channel);
        getRDF(url,sq,q,channel,5);

        }else{
        sm(channel,"try !iata BRS to find location info for an airport IATA code");

        }
        
        
}



/**
tell the bot new shortcuts
*/

public void newShortcut(String message,String channel){
        
sm(channel,"creating new shortcut");		

int i=message.indexOf("wh4, new shortcut");
String msg=null;
        if(i!=-1){
	msg=message.substring(i+18).trim();

	//get the first part (starts With !)
	int j=msg.indexOf("select");
	String shortpart=msg.substring(0,j).trim();

	shortpart=shortpart.substring(0,shortpart.indexOf(" ")).trim();

	//get the secon part (a query)
	String longpart=msg.substring(j);

	//store in a hash
	commands.put(shortpart,longpart);
	serializeCommands(filename);//testing

        commandstxt=getCommands(commandstxt);

	}else{
        sm(channel,"teach the bot commands like this: wh4, !bla $1 is select ?tt, ?bb where (pred:a ?tt ?bb) and ?tt ~ '$1'");

	}
}//end shortcut method



/**
for asking new queryies
shoudl look a bit like this
wh4, !bla $1 is select ?tt, ?bb where (pred:a ?tt ?bb) and ?tt ~ '$1'
*/

public void getTemplatedQuery(String message, String querytemplate,
String channel){

//all we have to do is replace $
//try just one $ for now
//assume just one keyword

//String keyw=message.substring(message.indexOf(" ")).trim();
//try several keywords

Vector keyws=Util.splitByString(message," ");
String query=querytemplate;
System.out.println("kw size "+keyws.size());

	for (int i=0;i<keyws.size();i++){

query=Util.replace(query,"$"+i,(String)keyws.elementAt(i));

System.out.println(" i is "+i);
System.out.println("KW is "+(String)keyws.elementAt(i));
System.out.println("QT is "+query);

	}

System.out.println("finidhed; asking query "+query);

getRDF(url,query,null,channel,5);


}//end gettemplatedquery



public void getSource(String message,String channel){
int limit=5;
int i=message.indexOf(" ");
String q=null;
        if(i!=-1){q=message.substring(i+1);
        String
url="http://swordfish.rdfweb.org/discovery/2001/08/codepict/sourcerdfxml.jsp?query="; 
        String sq="select ?term, ?source where "+
        " (test:sourceOf ?source ?term) "+
        " using test for http://xmlns.com/test/";
        getRDF(url,sq,q,channel,4);
        }else{
        sm(channel,"try !source 035a92bbdbf7c39a72b5534cc79058d25d0e7d6 "+
"to find where instances of that string are held. Exact match only");
        }

}


public String getCommands(String commandstext){

commandstxt="";

Enumeration e1=oldcommands.keys();

while(e1.hasMoreElements()){
commandstxt=commandstxt+" "+(String)e1.nextElement();
}

Enumeration e2 = commands.keys();

while(e2.hasMoreElements()){
commandstxt=commandstxt+", "+(String)e2.nextElement();
}

return commandstxt;

}


//read in file


public void readCommands(String uri){  

//if(uri==null){uri="file:commands.rdf";}

String query="select ?shortname, ?query where "+
"(test:shortname ?shortcut ?shortname) (test:query ?shortcut ?query) "+
"using test for http://example.com/test/";

        Graph gr = new Graph(null, uri, Util.RDFXML);
        gr.load();
        java.sql.ResultSet r=gr.askSquish(query);

        try{
        while (r.next()) {
        String shortname=(String)r.getString("shortname");
        String q=(String)r.getString("query");
        System.out.println("short "+shortname+" q "+q);
        commands.put(shortname,q);     
        }
        }catch(Exception ex){

        }
}



//serialize file

public void serializeCommands(String filen){
        
String st="<rdf:RDF \n"+
"  xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' \n"+
"  xmlns:test='http://example.com/test/' \n"+
">\n";
        
String fin="</rdf:RDF>";
String rdf = st;
Enumeration e = commands.keys();
while(e.hasMoreElements()){
String key = (String)e.nextElement();
String val=(String)commands.get(key);
 
rdf=rdf+"\n<rdf:Description>\n"+
"<test:shortname>"+key+"</test:shortname>\n"+
"<test:query>\n"+val+
"\n</test:query>\n</rdf:Description>\n";
}

rdf=rdf+fin;

Util.save(filen,"",rdf);

}


///

public void getInfo(String message, String channel){

int i=message.indexOf(" ");
String mm=null;
        
        if(i!=-1){
        mm=message.substring(i+1).trim();

	String val=(String)commands.get(mm);

	if(val!=null){
	sm(channel,"shortcut "+mm+" is "+val);
	}else{

	val=(String)oldcommands.get(mm);

		if(val!=null){
		sm(channel,"built-in command "+mm+" is "+val);
		}else{
	        sm(channel,"sorry, no command found for "+mm);
		}

	}

	}else{
        sm(channel,"sorry, no command found for "+mm);
	}


}


}
