/*
 *  $Id: rdfbrowser2.js,v 1.7 2008/05/23 22:47:24 bkutil Exp $
 *
 *  This file is part of the OpenLink Software Ajax Toolkit (OAT) project.
 *
 *  Copyright (C) 2005-2007 OpenLink Software
 *
 *  See LICENSE file for details.
*/

/*
	rb = new OAT.RDFBrowser2("div",optObj);
	
	rb.toXML();
	rb.fromXML();
	rb.getTitle(item);
	rb.getContent(value);
	rb.getURI(item);
	rb.processLink(domNode, href, disabledActions);
	
	#rdf_side #rdf_cache #rdf_filter #rdf_tabs #rdf_content
	
	data.triples
	data.structured
	
*/

OAT.RDFBrowser2 = function(div,optObj) {
	var self = this;

	this.options = {
		maxLength:30,
		maxURILength:60,
		maxDistinctValues:100,
		imagePath:OAT.Preferences.imagePath,
		imagePrefix:'RDFB',
		defaultURL:"",
		appActivation:"click",
		endpoint:"/sparql?query=",
		defaultQuery:"Data Source URI"
	}
	for (var p in optObj) { this.options[p] = optObj[p]; }

	/* default pragmas */
	this.dataRetrievalOpts = {
		cachingSchemes:'get::soft',
		pathTrSchemes:'grab::all',
		maxNodesRetrieved:100,
		maxNodesCrawled:1
	}
	
	this.parent = $(div);
	this.tabs = [];
	this.lastQueries = [];
	this.tree = false;
	this.uri = false;
	
	this.throbber = false;
	this.throbberElm = false;
	this.ajaxEnd = function() {
		if (self.throbber) {
			if (self.throbberElm) {
				self.throbber.parentNode.replaceChild(self.throbberElm,self.throbber);
			} else {
				OAT.Dom.unlink(self.throbber);
			}
			self.throbber = false;
			self.throbberElm = false;
		}
		if (OAT.AnchorData.window) { OAT.AnchorData.window.close(); }
	}

	this.bookmarks = {
		items:[],
		
		init:function() {
			self.bookmarks.redraw();
			
			var obj = OAT.Dom.uriParams();
			if (!("bmURI" in obj)) { return; }
			var uris = obj.bmURI;
			var labels = obj.bmLabel;
			for (var i=0;i<uris.length;i++) {
				var uri = decodeURIComponent(uris[i]);
				var label = decodeURIComponent(labels[i]);
				self.bookmarks.add(uri,label);
			}
		},
		
		add:function(uri,label) {
			var query = "CONSTRUCT { ?property ?hasValue ?isValueOf } FROM <{graph}> WHERE { {  <{uri}> ?property ?hasValue . } UNION {   ?isValueOf ?property <{uri}> . } }";
			query = query.replace(/{uri}/g,uri).replace(/{graph}/g,self.uri);
			var u = self.options.endpoint+encodeURIComponent(query);
			var o = {
				uri:uri,
				label:label
			}
			self.bookmarks.items.push(o);
			self.bookmarks.redraw();
			self.store.redraw();
		},

		remove:function(index) {
			self.bookmarks.items.splice(index,1);
			self.bookmarks.redraw();
		},

		redraw:function() {
			var removeRef = function(a,index) {
				OAT.Dom.attach(a,"click",function(){self.bookmarks.remove(index);});
			}

			OAT.Dom.clear(self.bookmarkDiv);
			var d = self.bookmarkDiv;
			for (var i=0;i<self.bookmarks.items.length;i++) {
				var item = self.bookmarks.items[i];
				var li = OAT.Dom.create("li");
				var a = OAT.Dom.create("a");
				a.innerHTML = item.label;
				a.href = item.uri;
				var r = OAT.Dom.create("a");
				r.href = "javascript:void(0)";
				r.innerHTML = "Remove";
				removeRef(r,i);
				OAT.Dom.append([li,a]);
				OAT.Dom.append([d,a,OAT.Dom.text(" - "),r,OAT.Dom.create("br")]);
				self.processLink(a,item.uri,OAT.RDFData.DISABLE_BOOKMARK);
			}
			if (!self.bookmarks.items.length) {
				var li = OAT.Dom.create("li");
				li. innerHTML = "No bookmarks.";
				OAT.Dom.append([self.bookmarkDiv,li]);
			}
		},
		
		toURL:function() {
			var result = "";
			for (var i=0;i<self.bookmarks.items.length;i++) {
				var item = self.bookmarks.items[i];
				result += encodeURIComponent("bmURI[]")+"="+encodeURIComponent(item.uri)+"&";
				result += encodeURIComponent("bmLabel[]")+"="+encodeURIComponent(item.label)+"&";
			}
			return result;
		}
	}
	
	this.reset = function(hard) { /* triples were changed */
		for (var i=0;i<self.tabs.length;i++) { self.tabs[i].reset(hard); }
		self.redraw(); /* redraw global elements */
	}
	
	this.store = new OAT.RDFStore(self.reset,{ajaxEnd:self.ajaxEnd});
	this.store.div = OAT.Dom.create("div");
	this.store.div.id = "store_items";
	this.data = self.store.data;
	
	this.store.redraw = function() {
		OAT.Dom.clear(self.store.div);
		var total = 0;
		var removeRef = function(a,url) {
			OAT.Dom.attach(a,"click",function(){self.store.remove(url);});
		}
		var checkRef = function(ch,url) {
			var f = function() {
				if (ch.checked) { self.store.enable(url);} else { self.store.disable(url); }
			}
			OAT.Dom.attach(ch,"click",f);
			OAT.Dom.attach(ch,"change",f);
		}

		var base = window.location.toString().match(/^[^?#]+/)[0];
		var th = base+"?";
		$("search_list").innerHTML = '';

		for (var i=0;i<self.store.items.length;i++) {
			var d = OAT.Dom.create("div");
			OAT.Dom.addClass(d,"storage_item");
			var item = self.store.items[i];
			total += item.triples.length;
			
			var ch = OAT.Dom.create("input");
			ch.type = "checkbox";
			ch.checked = item.enabled;
			ch.defaultChecked = item.enabled;
			
			var a = OAT.Dom.create("a");
//			a.href = item.href;
			var label = (item.href.length > self.options.maxURILength ? item.href.substring(0,self.options.maxURILength) + "..." : item.href);
			a.innerHTML = label;

			var t = OAT.Dom.text(" - "+item.triples.length+" triples - ");
			OAT.Dom.append([d,ch,OAT.Dom.text(" "),a,t]);
			self.processLink(a,item.href,OAT.RDFData.DISABLE_DEREFERENCE);
			
			
			var remove = OAT.Dom.create("a");
			remove.href = "javascript:void(0)";
			remove.innerHTML = "Remove from storage";
			removeRef(remove,item.href);
			checkRef(ch,item.href);
			
			var perm = OAT.Dom.create("a");
			perm.innerHTML = "permalink";
			perm.href = base+"?uri="+encodeURIComponent(item.href);
			th += encodeURIComponent("uri[]")+"="+encodeURIComponent(item.href)+"&";
			
			OAT.Dom.append([d,remove,OAT.Dom.text(" - "),perm],[self.store.div,d]);
			if (item.href.substring(0,5)=='http:') {
				$("search_list").innerHTML += '<input type="checkbox" checked="checked" value="'+label+'" id="searchscope'+i+'"> <label for="searchscope'+i+'">' + label + "</label><br/>";
			}
		}

		if (!$("search_list").innerHTML) {
			$("search_list").innerHTML = '<div>Nothing to search in</div>';
		} else {
			$("search_list").innerHTML = '<div>Select search scope:</div>' + $("search_list").innerHTML;
		}

		$("storage_permalink").href = th + self.bookmarks.toURL();

		/* display toggler and purge storage or not */
		if (self.store.items.length) {
			OAT.Dom.hide('welcome');
			OAT.Dom.show("storage_controls");
			OAT.Dom.show("storage_toggle");
		} else {
			OAT.Dom.hide("storage_controls");
			OAT.Dom.hide("storage_toggle");
		}

		if (!$("storage_total")) {
			var d = OAT.Dom.create("div");
			d.id = "storage_total";
			$("rdf_storage").appendChild(d);
		} else {
			var d = $("storage_total");
		}
		d.innerHTML = "Total "+total+" triples";
	}

	this.store.addSPARQL = function(q) {
		var url = self.options.endpoint+encodeURIComponent(q)+"&format=rdf";
		self.store.addURL(url);
	}
	
	this.throbberReplace = function(elm,replace) {
		return function(xhr) {
			var t = OAT.Dom.create("img",{cursor:"pointer"});
			t.id = "loading";
			OAT.Event.attach(t,"click",xhr.abort);
			t.src = self.options.imagePath + "Dav_throbber.gif";
			self.throbber = t;
			self.throbberElm = replace ? elm : false;
			if (replace) {
				elm.parentNode.replaceChild(t,elm);
			} else {
				elm.parentNode.insertBefore(t,elm);
			}
		}
	}

	this.store.loadFromInput = function() {
		if ($v(self.store.url)==self.options.defaultQuery) self.store.url.value = "";
		if (OAT.Browser.isIE && !$v(self.store.url)) { /* explorer gives an error with blank query */
			alert('Empty query.');
			return;
		}
		self.store.addURL($v(self.store.url),self.btnStart);
		self.addToPrevQueries($v(self.store.url));
	}

	this.store.init = function() {
		var url = OAT.Dom.create("input");
		url.size = 90;
		url.type = "text";
		url.title = "Data source URI";
		url.id = "inputquery";
		url.value = self.options.defaultURL;
		self.store.url = url;
		
		var btn1 = OAT.Dom.create("input");
		btn1.type = "button";
		btn1.value = "Query";
		btn1.id = "querybutton";
		btn1.title = "Go!";

		self.btnStart = self.throbberReplace(btn1,false);

		OAT.Dom.append([self.inputDiv,url,btn1,OAT.Dom.text(" ")]);
		OAT.Dom.append([self.storageDiv,self.store.div]);
		OAT.Dom.attach(url,"keypress",function(event) {
			if (event.keyCode == 13) { self.store.loadFromInput(); }
		});
		OAT.Dom.attach(btn1,"click",self.store.loadFromInput);

		/* querystring url */
		var obj = OAT.Dom.uriParams();
		if (!("uri" in obj)) { return; }
		if (typeof(obj.uri) == "object") { /* array of uris */
			for (var i=0;i<obj.uri.length;i++) {
				self.store.addURL(obj.uri[i]);
			}
		} else {
			self.store.addURL(obj.uri);
		}
	}

	this.addTab = function(type,label,optObj) {
		var obj = new OAT.RDFTabs[type](self,optObj);
		self.tabs.push(obj);
		var li = OAT.Dom.create("li");
		li.innerHTML = label;
		self.tabsUL.appendChild(li);
		self.tab.add(li,obj.elm);
		self.tab.go(0);
	}

	this.processLink = function(domNode,href,disabledActions) { /* assign custom things to a link */
		var genRef = function() {
			var list = self.generateURIActions(href,disabledActions);
			var ul = OAT.Dom.create("ul",{paddingLeft:"20px",marginLeft:"0px"});
			for (var i=0;i<list.length;i++) {
				if (list[i]) {
					var elm = OAT.Dom.create("li");
					elm.appendChild(list[i]);
				} else {
					var elm = OAT.Dom.create("hr");
				}
				ul.appendChild(elm);
			}
			return ul;
		}
			
		var obj = {
			title:"URL",
			content:genRef,
			width:300,
			height:200,
			result_control:false,
			activation:self.options.appActivation
		};
		OAT.Anchor.assign(domNode,obj);
		
		/* maybe image links */
		var node = $(domNode);
		if (!node.parentNode) { return; } /* cannot append images when no parent is available */
		var images = self.generateImageActions(href,disabledActions);
		var next = node.nextSibling;
		for (var i=0;i<images.length;i++) {
			node.parentNode.insertBefore(images[i],next);
		}
	}
	
	this.generateURIActions = function(href,disabledActions) {
		var list = [];
		
		if (!(disabledActions & OAT.RDFData.DISABLE_DEREFERENCE)) {
			var a = OAT.Dom.create("a");
			a.innerHTML = "Describe the attributes";
			a.href = "javascript:void(0)";
			var start1 = self.throbberReplace(a);
			OAT.Dom.attach(a,"click",function() {
				/* dereference link - add */
				self.store.addURL(href,start1);
			});
			list.push(a);
		}

		if (!(disabledActions & OAT.RDFData.DISABLE_DEREFERENCE)) {
			var a = OAT.Dom.create("a");
			a.innerHTML = "Describe - replace local storage";
			a.href = "javascript:void(0)";
			var start2 = self.throbberReplace(a);
			OAT.Dom.attach(a,"click",function() {
				/* dereference link - replace */
				var ref = function() {
					self.store.clear();
					start2();
				}
				self.store.addURL(href,ref);
			});
			list.push(a);
		}
			
		if (!(disabledActions & OAT.RDFData.DISABLE_DEREFERENCE)) {
			var a = OAT.Dom.create("a");
			a.innerHTML = "Describe - permalink";
			var root = window.location.toString().match(/^[^#]+/)[0];
			a.href = root+"#"+encodeURIComponent(href);
			list.push(a);
			list.push(false);
		}

		if (!(disabledActions & OAT.RDFData.DISABLE_FILTER)) {
			var a = OAT.Dom.create("a");
			a.innerHTML = "Relationships";
			a.href = "javascript:void(0)";
			OAT.Dom.attach(a,"click",function() {
				/* dereference link */
				OAT.AnchorData.window.close();
				self.store.addFilter(OAT.RDFStoreData.FILTER_URI,href);
			});
			list.push(a);
		}

		if (!(disabledActions & OAT.RDFData.DISABLE_BOOKMARK)) {
			var aa = OAT.Dom.create("a");
			aa.innerHTML = "Bookmark";
			aa.href = "javascript:void(0)";
			OAT.Dom.attach(aa,"click",function(){
				var label = prompt("Please name your bookmark:",href);
				self.bookmarks.add(href,label);
				OAT.AnchorData.window.close();
			});
			list.push(aa);
		}
		list.push(false);

		if (!(disabledActions & OAT.RDFData.DISABLE_HTML)) {
			var a = OAT.Dom.create("a");
			a.innerHTML = "(X)HTML Page Open";
			a.href = href;
			list.push(a);
		}
		return list;
	},
	
	this.generateImageActions = function(href,disabledActions) {
		var list = [];
		if (!(disabledActions & OAT.RDFData.DISABLE_DEREFERENCE)) {
			var img1 = OAT.Dom.create("img",{paddingLeft:"3px",cursor:"pointer"});
			img1.title = "Describe the attributes";
			img1.src = self.options.imagePath + "RDF_rdf.png";
			var start = self.throbberReplace(img1,true);
			OAT.Dom.attach(img1,"click",function() {
				/* dereference link - add */
				self.store.addURL(href,start);
			});
			list.push(img1);
		}

		
		if (!(disabledActions & OAT.RDFData.DISABLE_HTML)) {
			var a = OAT.Dom.create("a",{paddingLeft:"3px"});
			var img2 = OAT.Dom.create("img",{border:"none"});
			img2.src = self.options.imagePath + "RDF_xhtml.gif";
			a.title = "(X)HTML Page Open";
			a.appendChild(img2);
			a.target = "_blank";
			a.href = href;
			list.push(a);
		}
		return list;
	}
	
	this.drawPrevQueries = function() {
		var l = self.lastQueries.length;
		if (!l) {
			self.prevQueriesDiv.innerHTML = "<li id=\"noqueries\">No previous queries.</li>"
		} else {
			self.prevQueriesDiv.innerHTML = '';
			for (var i=0; i<l; i++) {
				var elem = OAT.Dom.create("li");
				self.prevQueriesDiv.appendChild(elem);
				elem.innerHTML = self.lastQueries[i];
				OAT.Dom.attach(elem,"click",function(event) {
					if (OAT.Browser.isIE) {
						var elem = event.srcElement;
					} else {
						var elem = event.target;
					}
					$('inputquery').value = elem.innerHTML;
					self.store.loadFromInput();
				});
			}
			var elem = OAT.Dom.create("li");
			elem.style.listStyleType = 'none';
			self.prevQueriesDiv.appendChild(elem);
			elem.innerHTML = "<i>Delete all previous queries</i>";
			OAT.Dom.attach(elem,"click",function(){
				if (window.confirm('All ('+self.lastQueries.length+') queries from this session will be deleted.')) {
					self.lastQueries = [];
					self.drawPrevQueries();
				}
			});
		}
	},


	this.addToPrevQueries = function(query) {
		if (self.lastQueries.find(query)<0) {
			self.lastQueries.reverse();
			self.lastQueries.push(query);
			self.lastQueries.reverse();
			self.drawPrevQueries();
		}
	},

	this.drawCategories = function() { /* category tree */

		if (!self.data.structured.length) {
			$('rdf_category').innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;No Categories.";
		} else {
			OAT.Dom.clear(self.categoryDiv);
		}

		var cats = {}; /* object of distinct values contained in filtered data */
		for (var i=0;i<self.data.structured.length;i++) {
			var item = self.data.structured[i];
			var preds = item.preds;
			for (var p in preds) {
				var pred = preds[p];
				for (var j=0;j<pred.length;j++) {
					var value = pred[j];
					if (typeof(value) == "object") { continue; }

					if (!(p in cats)) { cats[p] = {}; }
					var obj = cats[p];
					if (!(value in obj)) { obj[value] = 0; }
					obj[value]++;
				}
			}
		}

		/* 
			filter out some categories:
			* if there is only 1 element with such property
			* property count is > self.options.maxDistinctValues
			* if category contains 1 or 0 values
		*/
		for (var p in cats) {
			var count = 0;
			var atLeastOne = false;
			var obj = cats[p];
			for (var o in obj) {
				count++;
				if (obj[o] > 1) { atLeastOne = true; }
			}
			if ((!atLeastOne && p != "type") || (count <= 1 && p != "type") || count > self.options.maxDistinctValues) { delete cats[p]; }
		}
		
		function assign(node,p,o) {
			var ref = function() {
				self.store.addFilter(OAT.RDFStoreData.FILTER_PROPERTY,p,o);
			}
			OAT.Dom.attach(node,"click",ref);
		}
		
		var ul = OAT.Dom.create("ul");
		var bigTotal = 0;
		for (var p in cats) {
			var obj = cats[p];
			var li = OAT.Dom.create("li");
			var lilabel = OAT.Dom.create("span");
			li.appendChild(lilabel);
			lilabel.innerHTML = self.simplify(p);
			var ul2 = OAT.Dom.create("ul");
			li.appendChild(ul2);
			var count = 0;
			var total = 0;
			var anyli = OAT.Dom.create("li");
			var anya = OAT.Dom.create("a");
			anya.setAttribute("href","javascript:void(0)");
			anya.setAttribute("title","Filter by this value");
			anya.innerHTML = "[any]";
			anyli.appendChild(anya);
			ul2.appendChild(anyli);
			assign(anya,p,"");
			for (var o in obj) {
				count++;
				bigTotal++;
				var li2 = OAT.Dom.create("li");
				var a = OAT.Dom.create("a");
				a.setAttribute("href","javascript:void(0)");
				a.setAttribute("title",o);
				var label = self.simplify(o);
				if (label.length > self.options.maxLength) { label = label.substring(0,self.options.maxLength) + "&hellip;"; }
				a.innerHTML = label + " (" + obj[o] + ")";
				total += obj[o];
				li2.appendChild(a);
				ul2.appendChild(li2);
				assign(a,p,o);
			}
			lilabel.innerHTML += " ("+count+")";
			anya.innerHTML += " ("+total+")";
			ul.appendChild(li);
		}
		self.tree = new OAT.Tree({imagePath:self.options.imagePath,imagePrefix:self.options.imagePrefix,poorMode:(bigTotal > 1000),onClick:"toggle",onDblClick:"toggle"});
		self.tree.assign(ul,true);
		self.categoryDiv.appendChild(ul);
	}
	
	this.drawFilters = function() { /* list of applied filters */
		OAT.Dom.clear(self.filterDiv);

		function assignP(link,index) {
			var ref = function() {
				var f = self.store.filtersProperty[index];
				self.store.removeFilter(OAT.RDFStoreData.FILTER_PROPERTY,f[0],f[1]);
			}
			OAT.Dom.attach(link,"click",ref);
		}

		function assignU(link,index) {
			var ref = function() {
				var f = self.store.filtersURI[index];
				self.store.removeFilter(OAT.RDFStoreData.FILTER_URI,f);
			}
			OAT.Dom.attach(link,"click",ref);
		}

		for (var i=0;i<self.store.filtersProperty.length;i++) {
			var f = self.store.filtersProperty[i];
			var li = OAT.Dom.create("li");
			var value = (f[1] == "" ? "[any]" : f[1]);
			var strong = OAT.Dom.create("strong");
			strong.innerHTML = f[0]+": ";
			li.appendChild(strong);
			li.innerHTML += value+" ";
			var remove = OAT.Dom.create("a");
			remove.setAttribute("href","javascript:void(0)");
			remove.setAttribute("title","Remove this filter");
			remove.innerHTML = "[remove]";
			assignP(remove,i);
			li.appendChild(remove);
			self.filterDiv.appendChild(li);
		}
		
		for (var i=0;i<self.store.filtersURI.length;i++) {
			var value = self.store.filtersURI[i];
			var div = OAT.Dom.create("div");
			var strong = OAT.Dom.create("strong");
			strong.innerHTML = "URI: ";
			div.appendChild(strong);
			div.innerHTML += value+" ";
			var remove = OAT.Dom.create("a");
			remove.setAttribute("href","javascript:void(0)");
			remove.setAttribute("title","Remove this filter");
			remove.innerHTML = "[remove]";
			assignU(remove,i);
			div.appendChild(remove);
			self.filterDiv.appendChild(div);
		}

		if (!self.store.filtersURI.length && !self.store.filtersProperty.length) {
			var li = OAT.Dom.create("li");
			li.innerHTML = "No filters are selected. Create some by clicking on values in Categories you want to view.";
			self.filterDiv.appendChild(li);
		}
		
		if (self.store.filtersURI.length + self.store.filtersProperty.length > 1) {
			var div = OAT.Dom.create("div");
			var remove = OAT.Dom.create("a");
			remove.setAttribute("href","javascript:void(0)");
			remove.setAttribute("title","Remove all filters");
			remove.innerHTML = "remove all filters";
			OAT.Dom.attach(remove,"click",self.store.removeAllFilters);
			div.appendChild(remove);
			self.filterDiv.appendChild(div);
		}
	}
	
	this.redraw = function() { /* everything */
		self.drawCategories();
		self.drawFilters();
		self.store.redraw();
		self.bookmarks.redraw();
		for (var i=0;i<self.tabs.length;i++) {
			var tab = self.tab.tabs[i];
			if (i == self.tab.selectedIndex || tab.window) { self.tabs[i].redraw(); }
		}
	}

	this.getContent = function(data_,disabledActions) {
		var content = false;
		var data = (typeof(data_) == "object" ? data_.uri : data_);
		var type = self.getContentType(data);
		
		switch (type) {
			case 3:
				content = OAT.Dom.create("img");
				content.title = data;
				content.src = data;
				self.processLink(content,data);
			break;
			case 2:
				content = OAT.Dom.create("a");
				var r = data.match(/^(mailto:)?(.*)/);
				content.innerHTML = r[2];
				content.href = 'mailto:'+r[2];
			break;
			case 1:
				content = OAT.Dom.create("span");
				var a = OAT.Dom.create("a");
				a.innerHTML = data;
				a.href = data;
				content.appendChild(a);
				self.processLink(a,data,disabledActions);
			break;
			default:
				content = OAT.Dom.create("span");
				content.innerHTML = data;
				/* create dereference a++ lookups for all anchors */
				var anchors_ = content.getElementsByTagName("a");
				var anchors = [];
				for (var j=0;j<anchors_.length;j++) { anchors.push(anchors_[j]); }
				for (var j=0;j<anchors.length;j++) {
					var a = anchors[j];
					if (a.href.match(/^http/)) {
						self.processLink(a,a.href); 
					}
				}
			break;
		} /* switch */
		return content;
	}
	
	this.simplify = self.store.simplify;
	this.getContentType = self.store.getContentType;
	this.getTitle = self.store.getTitle;
	this.getURI = self.store.getURI;
	
	this.init = function() {
		/* dom */
		self.inputDiv = $("rdf_input");

		self.categoryDiv = $("rdf_category");
		if (!self.categoryDiv) { 
			self.categoryDiv = OAT.Dom.create("li",{});
			self.categoryDiv.id = "rdf_category";
			$('category_ul').appendChild(self.categoryDiv);
		}

		self.bookmarkDiv = $("bookmark_ul");
		if (!self.bookmarkDiv) { 
			self.bookmarkDiv = OAT.Dom.create("li",{});
			self.bookmarkDiv.id = "bookmark_ul";
			$('bookmark_ul').appendChild(self.bookmarkDiv);
		}

		self.sideDiv = $("rdf_side");
		if (!self.sideDiv) { 
			self.sideDiv = OAT.Dom.create("div",{});
			self.sideDiv.id = "rdf_side";
			self.parent.appendChild(self.sideDiv);
		}

		self.storageDiv = $("rdf_storage");
		if (!self.storageDiv) { 
			self.storageDiv = OAT.Dom.create("div",{});
			self.storageDiv.id = "rdf_storage";
			self.parent.appendChild(self.storageDiv);
		}

		self.filterDiv = $("filters_ul");
		if (!self.filterDiv) { 
			self.filterDiv = OAT.Dom.create("ul",{});
			self.filterDiv.id = "rdf_filter";
			$("filters_ul").appendChild(self.filterDiv);
		}

		self.prevQueriesDiv = $("prevQueries_ul");
		if (!self.prevQueriesDiv) { 
			self.prevQueriesDiv = OAT.Dom.create("ul",{});
			self.prevQueriesDiv.id = "prevQueries_ul";
			$("prevQueries_ul").appendChild(self.prevQueriesDiv);
		}

		self.tabsUL = $("rdf_tabs");
		if (!self.tabsUL) { 
			self.tabsUL = OAT.Dom.create("ul",{});
			self.tabsUL.id = "rdf_tabs";
			self.parent.appendChild(self.tabsUL);
		}

		self.tabDiv = $("rdf_content");
		if (!self.tabDiv) { 
			self.tabDiv = OAT.Dom.create("div",{});
			self.tabDiv.id = "rdf_content";
			self.parent.appendChild(self.tabDiv);
		}
		
		self.tab = new OAT.Tab(self.tabDiv,{dockMode:true,dockElement:"rdf_tabs"});
		self.descDiv = OAT.Dom.create("div");
		self.tabDiv.insertBefore(self.descDiv,self.tabDiv.firstChild);


		var actTab = function(index) {
			self.tabs[index].redraw();
		}
		self.tab.options.onDock = actTab;
		self.tab.options.onUnDock = actTab;
		self.tab.options.goCallback = function(oldIndex,newIndex) {
			if (OAT.AnchorData.window) { OAT.AnchorData.window.close(); }
			self.tabs[newIndex].redraw();
			self.descDiv.innerHTML = self.tabs[newIndex].description;
		}

		self.redraw();
		self.store.init();
		self.bookmarks.init();
		self.drawPrevQueries();
	}
	
	this.toXML = function(xslStr) {
		var xml = '<?xml version="1.0" ?>\n';
		if (xslStr) { xml += xslStr+'\n'; }
		xml += '<rdfbrowser tab="'+self.tabsUL.childNodes[self.tab.selectedIndex].innerHTML+'">\n';
		for (var i=0;i<self.store.items.length;i++) {
			var item = self.store.items[i];
			xml += '\t<uri>'+OAT.Dom.toSafeXML(item.href)+'</uri>\n';
		}
		for (var i=0;i<self.bookmarks.items.length;i++) {
			var item = self.bookmarks.items[i];
			xml += '\t<bookmark label="'+OAT.Dom.toSafeXML(item.label)+'">'+OAT.Dom.toSafeXML(item.uri)+'</bookmark>\n';
		}
		
		xml += '</rdfbrowser>\n';
		return xml;
	}
	
	this.fromXML = function(xmlDoc) {
		self.store.clear();
		self.store.removeAllFilters();
		var items = xmlDoc.getElementsByTagName("uri");
		for (var i=0;i<items.length;i++) {
			var item = items[i];
			var href = OAT.Xml.textValue(item);
			self.store.addURL(OAT.Dom.fromSafeXML(href));
		}
		var items = xmlDoc.getElementsByTagName("bookmark");
		for (var i=0;i<items.length;i++) {
			var item = items[i];
			var label = OAT.Dom.fromSafeXML(item.getAttribute("label"));
			var uri = OAT.Xml.textValue(item);
			self.bookmarks.add(OAT.Dom.fromSafeXML(uri),label);
		}
		var b = xmlDoc.getElementsByTagName("rdfbrowser")[0];
		var label = b.getAttribute("tab");
		var index = -1;
		for (var i=0;i<self.tabsUL.childNodes.length;i++) {
			var l = self.tabsUL.childNodes[i].innerHTML;
			if (l == label) { index = i; }
		}
		if (index != -1) { self.tab.go(index); }
		
	}
	
	this.fromRQ = function(data,clear) {
		if (clear) {
			self.store.clear();
			self.store.removeAllFilters();
		}
		var q = "";
		var d = data.replace(/[\r\n]/g," \n");
		var parts = d.split("\n");
		for (var i=0;i<parts.length;i++) {
			var part = parts[i].replace(/\n/g,"");
			var r = part.match(/^[^#]*/);
			q += r[0];
		}
		self.store.addSPARQL(q);
		if (clear) { self.tab.go(0); }
	}

	this.init();
}
