/*******************************************************************************
 * Copyright (c) 2007, 2008 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
dojo.provide("org.eclipse.cosmos.provisional.dr.ps.components.utility.common");
dojo.require("dijit.Dialog");
dojo.require("dijit.TitlePane");
dojo.require("dijit.form.Button");
dojo.require("dijit.form.TextBox");
dojo.require("org.eclipse.cosmos.provisional.dr.ps.components.data.WidgetStore");
dojo.requireLocalization("nls.org.eclipse.cosmos.provisional.dr.ps.components", "utility");
dojo.declare(
		"org.eclipse.cosmos.provisional.dr.ps.components.utility.UIContext",
		null,
		{
			_message: dojo.i18n.getLocalization("nls.org.eclipse.cosmos.provisional.dr.ps.components", "utility"),
			started:false,
			localeObj: null,
			idCounter:0,
			namespace:"_C_O",
			constructor: function(params){
				dojo.mixin(this,params);
			 	this.initialize();
			 	dojo.subscribe("org.eclipse.cosmos.provisional.dr.ps.components.utility.UIContext", this, this.setUIContext);			 	
			},
			initialize:function(){
				var self = this;	
				this.widgetStore = new org.eclipse.cosmos.provisional.dr.ps.components.data.WidgetStore();
				this.widgetStore.initialize({onInit:function(){
			   		self.getStyleProperties("_cosmos_context_", function(data){
						if ((data) && (data.view)){
							if (data.view.errorHandler){
								self.log = self.createObject(data.view.errorHandler);
								self.log._context = self;
							}
							if (data.view.localeHandler){
								self.localeObj = self.createObject(data.view.localeHandler);
							}
						}
						if (!self.log){
							self.log = new org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorHandler();
							self.log._context = self;
						}
						if (!self.localeObj)
							self.localeObj = new org.eclipse.cosmos.provisional.dr.ps.components.utility.Localization();
						dojo.publish("initializeWidget", [{context:self}]);
					 	self.started = true;
				   		}
			   		);
				}});
                this.xmlFormatter = new org.eclipse.cosmos.provisional.dr.ps.components.utility.XMLFormatter();
			},
			setUIContext: function(obj){
			  		if (obj)
			   			obj.setUIContext(this);
			},			
			getString: function(bundle, key){
				this.localeObj.getString(bundle, key);
			},
			getStyleProperties :function(tag, onItem){		
				this.widgetStore.getWidgetProperties({tags:tag, onItem:onItem});
			},	
			createObject :function(prop, cell){       		
				//create widget		
				var properties = dojo.clone(prop);
		
				properties.UIContext = this;
				if (properties.clazz){
					return eval("new "+properties.clazz+"(properties, cell)");
				}
				return null;
			
			},
			createWidgetView :function(tag, parentWidget, widgetCallback, cell, contextMap){
				var self = this;
		   		this.getStyleProperties(tag, function(data){
		   			var style = dojo.clone(data);
		   			if ((style) && (style.view)){   				
		   				
			   			style.view.parentWidget = parentWidget;
			   			
			   			var widgetProperties = style.view;
						widgetProperties.UIContext = self;
						if (dojo.isArray(tag)){
							widgetProperties.attachPoint = tag[tag.length-1];
						}
						else{
							widgetProperties.attachPoint = tag;
						}
						widgetProperties.contextMap = contextMap;
						widgetProperties.dataMap = style.dataMap;
						var viewObject = dojo.getObject(widgetProperties.clazz);
						if (dojo.isFunction(viewObject)){
							//need to see if we already created the object
							var oldWidget = dijit.byId(widgetProperties.id);
							if (oldWidget)
								oldWidget.destroy();
							//We need to see if this is a pure function or an object constructor...
							if (!widgetProperties.id){
								widgetProperties.id = self.namespace+self.idCounter;
								if (!widgetProperties.widgetId){
									widgetProperties.widgetId = widgetProperties.id;
								}
								self.idCounter++;
							}
							
							var widget = new viewObject(widgetProperties, cell);
						//call callback to with widget			
							if (widgetCallback)
								widgetCallback(widget);
							return true;
						}
					}
					return false;
		   		});
				
			},	
			getService:function(data, namespace){
				if (data.services){
					var t = data.services[0];
					for (var y=0; y < data.services.length; y++){
						var service= data.services[y];
						if (service[0]==namespace){
							return service[1];
						}
					}
				}
				return null;
			},
			submitRequest:function(keyArgs){
					var handleAs = "json-comment-optional";
					if (keyArgs.handleAs)
						handleAs = keyArgs.handleAs;
					var deferred = dojo.rawXhrPost({
				        url: keyArgs.url,
						handleAs: handleAs,
				        postData: keyArgs.postData,
				        onItem: keyArgs.onItem,
				        handle: function(response, ioArgs){
				                //This function handles the response.
				                //Inside this function, the "this" variable
				                //will be the object used as the argument to the dojo.xhrGet() call.
								if(response instanceof Error){
				                        if(response.dojoType == "cancel"){
				                                //The request was canceled by some other JavaScript code.						                        	   
				                        		if (log) _self.log.logInfo (dojo.string.substitute(_self._message.REQUEST_CANCEL, [_self.url, response]));
				                        }else if(response.dojoType == "timeout"){
				                                //The request took over 5 seconds to complete.
			                        		if (log) _self.log.logInfo (dojo.string.substitute(_self._message.REQUEST_TIMEOUT, [_self.url, response]));
				                        }else{
				                                //Some other error happened.
			                        		if (log) _self.log.logInfo (dojo.string.substitute(_self._message.REQUEST_ERROR, [_self.url, response]));
				                        }
				                }
								else if (response._error_){	
									//need to decode string messages
									var detail = unescape(response.detail);
									var message = unescape(response.message);
									rExp = /\+/gi;
									response.detail=detail.replace(rExp, " ");				
									response.message=message.replace(rExp, " ");
									if (log)
										_self.log.logError(response,true);					
									if(keyArgs.onError){
											var scope = keyArgs.scope ? keyArgs.scope : dojo.global;
											keyArgs.onError.call(scope, response);
									}
									 
								}
	                        	this.onItem(response);
				                //If you think there could be other callback handlers registered with this deferred, then
				                //return response to propagate the same response to other callback handlers. Otherwise,
				                //the error callbacks may be called in the success case.
				                return response;
				        }
				});							
			},
			submitQuery:function(keyArgs){
				var item = keyArgs.item;
				var query = keyArgs.queryObject;
				var success = false;
				var log = true;
				var _self = this;
				var handleAs = "json-comment-optional";
				if (query.handleAs)
					handleAs = query.handleAs;				
				if (keyArgs.log == false)
					log = keyArgs.log;
				if (typeof(query["queryHandler"]) != 'undefined'){
					//map input item to parameters of the query
					var postData = "";
						if (query.bindInput){
							var bindQueryFunc = function(propertiesArgs){
								query.bindInput(item, function(postDataArgs){
								//IE doesn't allow json object as post Data
								if (!(dojo.isString(postDataArgs)))
									postDataArgs = "";
								if (dojo.isString(propertiesArgs))
									postDataArgs += propertiesArgs;
								var deferred = dojo.rawXhrPost({
								        url: query["queryHandler"],
										handleAs: handleAs,
								        postData: postDataArgs,
								        queryObject: query,        
								        onItem: keyArgs.onItem,
								        handle: function(response, ioArgs){
								                //This function handles the response.
								                //Inside this function, the "this" variable
								                //will be the object used as the argument to the dojo.xhrGet() call.
												if(response instanceof Error){
								                        if(response.dojoType == "cancel"){
								                                //The request was canceled by some other JavaScript code.						                        	   
								                        		if (log) _self.log.logInfo (dojo.string.substitute(_self._message.REQUEST_CANCEL, [_self.url, response]));
								                        }else if(response.dojoType == "timeout"){
								                                //The request took over 5 seconds to complete.
							                        		if (log) _self.log.logInfo (dojo.string.substitute(_self._message.REQUEST_TIMEOUT, [_self.url, response]));
								                        }else{
								                                //Some other error happened.
							                        		if (log) _self.log.logInfo (dojo.string.substitute(_self._message.REQUEST_ERROR, [_self.url, response]));
								                        }
								                }
												else if (response._error_){	
													//need to decode string messages
													var detail = unescape(response.detail);
													var message = unescape(response.message);
													rExp = /\+/gi;
													response.detail=detail.replace(rExp, " ");				
													response.message=message.replace(rExp, " ");
													if (log)
														_self.log.logError(response,true);					
													if(keyArgs.onError){
															var scope = keyArgs.scope ? keyArgs.scope : dojo.global;
															keyArgs.onError.call(scope, response);
													}
													 
												}
												else{				
								                	//should only store the record contents so that we don't load the full graph response when loading the record viewer
								                	//check to see if we have to transform the response before sending the data to the call back method
								                	if ((this.queryObject) && (typeof(this.queryObject.render) != 'undefined')){
							                        	this.onItem(this.queryObject.render(response));
						                        	}
								                	else{
							                        	this.onItem(response);
						                        	}
								                }
							                	if ((this.queryObject) && (typeof(this.queryObject.onComplete) != 'undefined')){
							                		this.queryObject.onComplete(response)
							                	}
								                //If you think there could be other callback handlers registered with this deferred, then
								                //return response to propagate the same response to other callback handlers. Otherwise,
								                //the error callbacks may be called in the success case.
								                return response;
								        }
								});							
								
							
							});
							}
							var currentItem = item;
							while ((currentItem) && (!currentItem.propertiesHandler)){
								if (currentItem.parentItem)
									currentItem = currentItem.parentItem[0];
								else
									currentItem = null;
							}
							if ((currentItem) && (currentItem.propertiesHandler)){
								//check parent nodes to see if there's secuirty handlers
								if (currentItem.propertiesHandler.canBind(item)){
									currentItem.propertiesHandler.bindInput(item, function(postDataArgs){
										bindQueryFunc(postDataArgs);
									});							
								}
							}
							else{
								bindQueryFunc("");
							}
							
						}
					}
				return success;
			}
});




//This demonstrates a query unit   
dojo.declare(
   "org.eclipse.cosmos.provisional.dr.ps.components.utility.BasicQuery",
	// superclass	
	null,
	{
		queryHandler: null,
		postData: "",
		constructor: function(params){
			dojo.mixin(this,params);
		},
		bindInput: function(data, callbackMethod){		
				callbackMethod(this.postData);
		},
		render: function(input){
			return input;
		},
		onComplete: function(input){
		}		
		}
); 

//This demonstrates a query unit   
dojo.declare(
   "org.eclipse.cosmos.provisional.dr.ps.components.utility.Localization",
	// superclass	
	null,
	{
			constructor: function(params){
				dojo.mixin(this,params);
			},
			getString: function(bundle, key){
				if (bundle.key)
					return bundle.key;
				return key;
			}
		}
); 

//Tree node query unit   
dojo.declare(
"org.eclipse.cosmos.provisional.dr.ps.components.utility.TreeNodeQuery",
	// superclass	
	null,
	{
		queryHandler: null,
		namespace:null,
		constructor: function(params){
			dojo.mixin(this,params);
		},
		bindInput: function(data, callbackMethod){
			var epr = data.epr;
			if ((this.namespace != null) && (data)){
				epr = this.UIContext.getService(data, this.namespace);
				if (epr == null)
					epr = data.epr;
			}
			
				callbackMethod("title="+data.title+"&epr="+escape(epr));
		},
		render: function(input){
			return input;
		}
	}
); 


//Tree node property query unit   
dojo.declare(
"org.eclipse.cosmos.provisional.dr.ps.components.utility.TreeNodePropertyQuery",
	// superclass	
	null,
	{
		queryHandler: null,
		constructor: function(params){
			dojo.mixin(this,params);
		},
		bindInput: function(data, callbackMethod){
				callbackMethod("title="+data.title+"&epr="+escape(data.epr)+"&prop=true");
		},
		render: function(input){
			return input;
		}
	}
); 


//Tree node CMDBf   
dojo.declare(
"org.eclipse.cosmos.provisional.dr.ps.components.utility.TreeNodeCMDBf",
	// superclass	
	null,
	{
		queryHandler: null,
		constructor: function(params){
			dojo.mixin(this,params);
		},
		bindInput: function(data, callbackMethod){
			if (data.object != null){
				callbackMethod("title="+data.title+"&epr="+escape(data.epr)+"&object="+data.object);
			}
		},
		render: function(input){
			return input;
		}
	}
); 


dojo.declare(
		   "org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorQuery",
			// superclass	
		   org.eclipse.cosmos.provisional.dr.ps.components.utility.BasicQuery,
			{
				queryHandler:"json?service=org/eclipse/cosmos/provisional/dr/drs/service/ErrorLogger",
				bindInput: function(data, callbackMethod){
			   		callbackMethod("message="+data.message+"&detail="+data.detail+"&sev="+data.severity);
				},
				render: function(input){
					return input;
				}
			}
		); 


dojo.declare(
		"org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorDialog",
		[dijit._Widget, dijit._Templated, dijit._Container], 
		{
			_message: dojo.i18n.getLocalization("nls.org.eclipse.cosmos.provisional.dr.ps.components", "utility"),
		 	title:"",
			message:"",	 	
			icon:"",
			detail:"",
			templatePath:dojo.moduleUrl("org.eclipse.cosmos.provisional.dr.ps.components.utility", "html/ErrorDialog.html"),
			widgetsInTemplate: true,
			widgetId: "errorDialog",
			show: function(){
				this.dialogBox.show();
			},
			onOk: function(){
				this.dialogBox.onCancel();
			},
			submitQuery: function(){
			},
			create: function(params, srcNodeRef) {
				//for some reason I need to destroy widget explicitly
	   			if (dijit.byId(this.widgetId) != null){
	   				dijit.byId(this.widgetId).destroy();
	   				dijit.byId(this.widgetId+"_ok").destroy();
	   			}
				this.okLbl=this._message.OK;
				org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorDialog.superclass.create.apply(this, arguments);
			},			
			postMixInProperties: function(){
				if (dojo.isObject(this.message)){
					if (this.message.title)
						this.title = this.message.title;
					if (this.message.detail)
						this.detail = this.message.detail;
					if (this.message.message)
						this.message = this.message.message;
				}
				//call superclass
				org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorDialog.superclass.postMixInProperties.apply(this, arguments);
			},
			postCreate: function(){
				//call superclass
				org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorDialog.superclass.postCreate.apply(this, arguments);
				this.dialogBox = dijit.byId(this.widgetId);
				//focus on the ok button
				dijit.byId(this.widgetId+"_ok").focus();
			},
			destroy: function(){
				//call superclass
				org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorDialog.superclass.destroy.apply(this, arguments);
				if (this.dialogBox){
					this.dialogBox.onCancel();
				}
				dijit.byId(this.widgetId+"_ok").destroy();
				this.inherited(arguments);
			}
			
			
		}
	);   
dojo.declare(
		"org.eclipse.cosmos.provisional.dr.ps.components.utility.ProgressDialog",
		[dijit._Widget, dijit._Templated, dijit._Container], 
		{
		 	title:"",
			message:"",	 	
			icon:"",
			detail:"",
			rollerImagePath:dojo.moduleUrl("dojox","off/resources/roller.gif").uri,			
			templatePath:dojo.moduleUrl("org.eclipse.cosmos.provisional.dr.ps.components.utility", "html/ProgressDialog.html"),
			widgetsInTemplate: true,
			widgetId: "progressDialog",
			show: function(){
				this.dialogBox.show();
			},
			onCancel: function(){
				this.dialogBox.onCancel();
			},
			
			
			setMessage: function(message) 
			{
				var messageElement = dojo.byId("message");
				messageElement.innerHTML = message;
				
			},		
			
			
			create: function(params, srcNodeRef) {
				//for some reason I need to destroy widget explicitly
	   			if (dijit.byId(this.widgetId) != null){
	   				dijit.byId(this.widgetId).destroy();
	   			}
				org.eclipse.cosmos.provisional.dr.ps.components.utility.ProgressDialog.superclass.create.apply(this, arguments);
			},			
			postCreate: function(){
				//call superclass
				org.eclipse.cosmos.provisional.dr.ps.components.utility.ProgressDialog.superclass.postCreate.apply(this, arguments);
				this.dialogBox = dijit.byId(this.widgetId);
			},
			destroy: function(){
				this.dialogBox.onCancel();
				//call superclass
				org.eclipse.cosmos.provisional.dr.ps.components.utility.ProgressDialog.superclass.destroy.apply(this, arguments);
			}
		}
	);   

dojo.declare(
		"org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorHandler",
		null,
		{
	 	serverHandler:null,
	 	serverQuery:null,
	 	_context:null,
		//defines a url that will recieve logged messages.
	 	ERROR:1,
	 	INFO:2,
	 	WARNING:4,
	 	NONE:0,
		//atribute that determins if the message should be logged to the dojo debug console.
	 	debug:7,
		//defines the dialog box that will show the message.
		promptDialog:null,
		//attribute that determines if a dialog box should be displayed when a message is logged
		prompt:false,
		persist:0,
		logTopic: null,
		constructor: function(params){
			dojo.mixin(this,params);
			this.logTopic = dojo.subscribe("org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorHandler", this, this.log);
		},
		destroy:function() {
			dojo.unsubscribe(this.logTopic);
		},
		log:function(keywordArgs) {
			if ((keywordArgs) && (keywordArgs.message)){
				var argPrompt = false;
				if (keywordArgs.prompt)
					argPrompt = true;
				if (keywordArgs.severity==this.ERROR){
					this.logError(keywordArgs.message,argPrompt);
				}
				else if (keywordArgs.severity==this.WARNING){
					this.logWarning(keywordArgs.message,argPrompt);
				}
				else{
					this.logInfo(keywordArgs.message,argPrompt);
				}
					
			}
		},
		logError:function(message, prompt) {
		// summary: logs an error messages
		// description: the message is logged as an error message.  If the prompt argument
	 	//    is set to true a dialog message is presented to the user.
			if (this.debug & this.ERROR)
				console.error(message);
			if ((prompt) || (this.promptDialog & this.ERROR)){
				this.dialog = new org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorDialog({icon:dojo.moduleUrl("org.eclipse.cosmos.provisional.dr.ps.components.utility", "html/images/error.gif"),title:"Error",message:message});
				this.dialog.show();
			}
			if (this.persist & this.ERROR){
				this.submitQuery(this.ERROR, message);
			}
		},
		logWarning:function(message, prompt) {
		// summary: logs a warning messages
		// description: the message is logged as a warning message.  If the prompt argument
	 	//    is set to true a dialog message is presented to the user.
			if (this.debug & this.WARNING)
				console.debug(message);
			if ((prompt) || (this.promptDialog & this.WARNING)){
				this.dialog = new org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorDialog({icon:dojo.moduleUrl("org.eclipse.cosmos.provisional.dr.ps.components.utility", "html/images/warning.gif"),title:"Warning",message:message});
				this.dialog.show();
			}
			if (this.persist & this.WARNING){
				this.submitQuery(this.WARNING,message);
			}
		},
		logInfo:function(message, prompt) {
		// summary: logs an informational messages
		// description: the message is logged as an informational message.  If the prompt argument
	 	//    is set to true a dialog message is presented to the user.
			if (this.debug & this.INFO)
				console.debug(message);
			if ((prompt) || (this.promptDialog & this.INFO)){
				this.dialog = new org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorDialog({icon:dojo.moduleUrl("org.eclipse.cosmos.provisional.dr.ps.components.utility", "html/images/inform.gif"),title:"Information",message:message});
				this.dialog.show();
			}
			if (this.persist & this.INFO){
				this.submitQuery(this.INFO, message);
			}
		},
		submitQuery:function(severity, message, detail){
			if (this._context != null){
				if (this.serverQuery == null)
					this.serverQuery = new org.eclipse.cosmos.provisional.dr.ps.components.utility.ErrorQuery();
				if (this.serverHandler != null)
					this.serverQuery.queryHandler= this.serverHandler;
				this._context.submitQuery({queryObject:this.serverQuery, item:{message:message, detail:detail, severity:severity}, log:false, onItem:function(data){
					//do we need to log data received from data feed?
				}});
			}
		}
});

dojo.declare(
		   "org.eclipse.cosmos.provisional.dr.ps.components.utility.PropertiesObject",
			// superclass	
			null,
			{
		        username:"",
		        password:"",
		        soapversion:"",
		        //Basic Constructor
				constructor: function(params){
					dojo.mixin(this,params);
				},
                //we can bind user name and password to the request parameters
				bindInput: function(data, callbackMethod){
		                      callbackMethod("&username="+this.username+"&password="+this.password+"&soapversion="+this.soapversion);
				},
				//return true if the property object should bind credentials to the request otherwise false is returned.
		        canBind:function(data){
		                return false;
		        },
				update:function(args){
					dojo.mixin(this,args);		        	
		        }
			}
); 

dojo.declare(
		   "org.eclipse.cosmos.provisional.dr.ps.components.utility.SimplePropertiesObject",
			// superclass	
			[org.eclipse.cosmos.provisional.dr.ps.components.utility.PropertiesObject],
			{
		        //return true if the property object should bind credentials to the request otherwise false is returned.
		       canBind:function(data){
                 return true;
               }
			}
); 


dojo.declare
(
	"org.eclipse.cosmos.provisional.dr.ps.components.utility.BasicUtility",
	null,
	{
		destroyWidgets: function(widgetIds)
		{
			for (var i = 0; i < widgetIds.length; i++)
			{
				var widget = dijit.byId(widgetIds[i]);
				if (widget)
				{
					widget.destroy();
				}
			}
		}
	}
);

dojo.declare(
		"org.eclipse.cosmos.provisional.dr.ps.components.utility.XMLFormatter",
		null,

	{
	ELEMENT_COLOR : "red",
	ATTRIBUTE_NAME_COLOR : "green",
	ATTRIBUTE_VALUE_COLOR : "blue",
	COMMENT_COLOR: "gray",

	//Method: formatRecordValue
	//Summary: Returns a formatted record value based on what is
	//passed in.  This method color codes the XML tags and properly
	//indents each element.
	format: function (value)
	{			
		var buffer = "";
		var currentChar = null;
		var i = 0;
		var indent = 0;
		var textContent = "";			
		while (i < value.length)
		{
			currentChar = value.charAt(i);
			
			// New element
			switch (currentChar)
			{
				case  '<':		
					if (textContent.length > 0)
					{
						buffer += this.addIndent(indent);
						buffer += textContent;
						buffer += "<br/>";
						textContent = "";
					}
					
					var result = this.formatElement (buffer, value, i, indent);
					i = result[0];
					indent = result[1];
					buffer = result[2];
					break;
					
				case '\n':	
				case '\r':
				case '\t':
				case ' ':
					i++;
					break;
				
				default:
					textContent += currentChar;
					i++;
					
			}			
		}
		
		return buffer;
	},


	//Method: formatElement
	//Summary: Formats the current element passed in
	formatElement: function(buffer, value, index, indent)
	{
		var currentChar = null;
		var isClosing = false;
		var isProcessor = false;
		
		while (index < value.length)
		{
			currentChar = value.charAt(index);
			switch (currentChar)
			{
				case '<':

					var result = null;
					
					// Determine if this is a comment
					if (index + 3 < value.length &&
						value.charAt(index+1) == '!' &&
						value.charAt(index+2) == '-' &&
						value.charAt(index+3) == '-')
					{					
						result = this.formatComment(buffer, value, index, indent);		
						return [result[0], indent, result[1]];			
					}
					else
					{
						// Is this a processor?
						isProcessor = value.charAt(index+1) == '?';
						
						// Is this a closing tag?
						isClosing = value.charAt(index+1) == '/'
						if (isClosing)
						{
							indent--;
						}
						
						buffer += this.addIndent(indent);						
						buffer += "&lt;";						
						index++;
						result = this.formatElementName(buffer, value, index, indent);
						
					}

					index = result[0];
					buffer = result[1];
					
					break;	

				case '?':
					buffer += currentChar;
					index++;
					break;
					
				case '>':
					if (value.charAt(index - 1) == '/')
					{
						buffer += '/';							
					}
					else if (!isClosing && !isProcessor)
					{
						indent++;
					}
																	
					index++;
					buffer += "&gt;<br/>";
					return [index, indent, buffer];

				case ' ':
				case '\t':
				case '\n':
				case '\r':
				case '/':
					index++;
					break;
					
				default:
					values = this.formatAttribute( buffer, value, index, indent);		
					index = values[0];
					buffer = values[1];
			}
		}
		
		return [index, indent, buffer];			
	},


	//Method: formatComment
	//Summary: Formats the comment section of an XML document
	formatComment: function (buffer, value, index, indent)
	{
		buffer += "<font color='" + this.COMMENT_COLOR + "'>";
		buffer += this.addIndent (indent);

		while (index < value.length)
		{
			currentChar = value.charAt(index);
			switch (currentChar)
			{
				case '<':
					buffer += "&lt;";
					index++;
					break;
					
				case '\n':
					buffer += "<br/>";
					buffer += this.addIndent (indent);
					index++;
					break;

				case '\t':
					index++;
					break;
				
				case '>':				
					if (index - 2 >= 0 &&
						value.charAt(index - 2) == '-',
						value.charAt(index - 1) == '-')
					{
						buffer += "&gt;"
						buffer += "<br/>"
						buffer += "</font>";
						index++;
						return [index, buffer];
					}
					else
					{
						buffer += "&gt;"
						index++;
					}
					break;																						
											
				default:
					buffer += currentChar;
					index++;
			}
		}			

		return [index, buffer];
	},


	//Method: formatElementName
	//Summary: Formats an element name based on the value and the index passed
	//in.  The color of element names can be controlled via this.ELEMENT_COLOR
	formatElementName: function (buffer, value, index, indent)
	{			
		var currentChar;
		buffer += "<font color='" + this.ELEMENT_COLOR + "'>";
		while (index < value.length)
		{
			currentChar = value.charAt(index);
			switch (currentChar)
			{
				case '>':						
				case ' ':														
					buffer += "</font>";						
					return [index, buffer];														
											
				default:
					buffer += currentChar;
					index++;
			}
		}			
		
		return [index, buffer];
	},


	//Method: formatAttribute
	//Summary: Formats an attribute based on the value and the index
	//passed in.  The color of attribute names/values can be controlled
	//via this.ATTRIBUTE_NAME_COLOR and this.ATTRIBUTE_VALUE_COLOR
	formatAttribute: function (buffer, value, index, indent)
	{		
		var currentChar;
		buffer += "<font color='" + this.ATTRIBUTE_NAME_COLOR + "'> ";
		var quoteNumber = 0;
		
		while (index < value.length)
		{
			currentChar = value.charAt(index);
			switch (currentChar)
			{
				case '=':
					buffer += "</font>";
					buffer += currentChar;
					index++;						
					buffer += "<font color='" + this.ATTRIBUTE_VALUE_COLOR + "'>";
					break;
				case '"':
					buffer += currentChar;
					index++;
					quoteNumber++;
					if (quoteNumber == 2)
					{
						buffer += "</font>";
						return [index, buffer];
					}
					break;
				default:
					buffer += currentChar;					
					index++;
			}
		}
		
		return [index, buffer];
	},


	//Method: addIndent
	//Summary: Adds 'indent' spaces to the buffer passed in
	addIndent: function (indent)
	{
		var buffer = "";
		for (var i = 0; i < indent; i++)
		{
			buffer += "&nbsp;";
		}
		
		return buffer;
	}
	}
)

dojo.addOnLoad(
	function(e) {
		new org.eclipse.cosmos.provisional.dr.ps.components.utility.UIContext();
	}
);
