incubator-xap-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmarga...@apache.org
Subject svn commit: r510832 [1/2] - in /incubator/xap/trunk: codebase/src/xap/xml/xmodify/ unittests/testsrc/xap/xmodify/
Date Fri, 23 Feb 2007 05:10:47 GMT
Author: jmargaris
Date: Thu Feb 22 21:10:45 2007
New Revision: 510832

URL: http://svn.apache.org/viewvc?view=rev&rev=510832
Log:
xnmodify patch from JIRA

Modified:
    incubator/xap/trunk/codebase/src/xap/xml/xmodify/CommandDirective.js
    incubator/xap/trunk/codebase/src/xap/xml/xmodify/DirectiveSet.js
    incubator/xap/trunk/codebase/src/xap/xml/xmodify/UpdateDirective.js
    incubator/xap/trunk/codebase/src/xap/xml/xmodify/Xmodify.js
    incubator/xap/trunk/codebase/src/xap/xml/xmodify/XmodifyException.js
    incubator/xap/trunk/codebase/src/xap/xml/xmodify/XmodifyNamespaceHandler.js
    incubator/xap/trunk/unittests/testsrc/xap/xmodify/_TestxModifyHTML.html
    incubator/xap/trunk/unittests/testsrc/xap/xmodify/xmodify.xal
    incubator/xap/trunk/unittests/testsrc/xap/xmodify/xmodifyHTML.xal

Modified: incubator/xap/trunk/codebase/src/xap/xml/xmodify/CommandDirective.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/xml/xmodify/CommandDirective.js?view=diff&rev=510832&r1=510831&r2=510832
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/xml/xmodify/CommandDirective.js (original)
+++ incubator/xap/trunk/codebase/src/xap/xml/xmodify/CommandDirective.js Thu Feb 22 21:10:45 2007
@@ -18,16 +18,17 @@
  */
 Xap.provide("xap.xml.xmodify.CommandDirective") ;
 
+Xap.require("xap.log.Logger");
 Xap.require("xap.xml.xmodify.XmodifyException");
 Xap.require("xap.xml.xmodify.UpdateDirective");
 Xap.require("xap.xml.dom.Document");
-Xap.require("xap.log.Logger");
-Xap.require("google.xpath");
+Xap.require("xap.util.MessageFormat");
 Xap.require("xap.util.XapException");
- 
+Xap.require("google.xpath");
+
 /**
- * @fileoverview An object embodying a particular operation (e.g., <code>append</code>) to be performed 
- * on a targetted part of the UI document (as specifically using either 
+ * @fileoverview An object embodying a particular operation (e.g., <code>append</code>)
+ * to be performed on a targetted part of the UI document (as specifically using either 
  * XPath or a Xap-specific syntax wrappering <code>getElementById()</code>.<b> 
  * 
  * @class  Command directives point to a document; they're 
@@ -38,955 +39,782 @@
  * particular directive is set (e.g., append a new child we've specified) 
  * and then that action is applied to the targets. Directives include any arguments
  * used in the operation, as specified in the defining tags' bodies.
- * <br/>
- * Here are some examples: <br/>
- * <br/>
- * Example 1: insert a new address record after the first record with id 0: <br>
- * <code><br/>
- * &nbsp;&nbsp;&nbsp; &lt;xm:insert-after select="id('0')"><br/> 
- * &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;     &lt;address id="1" /&gt;<br/>
- * &nbsp;&nbsp;&nbsp;  &lt;/xm:insert-after&gt;
- * <br/></code><br/><br/>
- * Example 2: set the 'grade' and 'nickname' attributes of a 
- * particular element named 'foo'<br>
- * <code><br/>
- * &nbsp;&nbsp;&nbsp; &lt;xm:set-attribute select="/baz/bar/foo"&gt;<br/>
- * &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;attribute name="grade" value="A1" /&gt;<br/>
- * &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;attribute name="nickname" value="B1" /&gt;<br/>
- * &nbsp;&nbsp;&nbsp; &lt;/xm:set-attribute&gt;
- * <br/></code>
  * @version modeled after Java $Revision: 1.18 $
  * @author xap@hisown.com
+ * @author mmikhaylov@nexaweb.com
  */
+ 
 //----------------------------------------------------------------------
 // Constructors.
 //----------------------------------------------------------------------
 
-xap.xml.xmodify.CommandDirective = function(elemDirectiveElement, session)
-{
-	//enough logging in here to be worth it to save a reference
+/**
+*
+*	@param directiveElement {Element} Xmodify directive like <append>, <replace>, etc.
+*	@param session {xap.session.ClientSession} Current Session object.
+*	@param directiveSet {xap.xml.xmodify.DirectiveSet} Parent instance of new DirectiveSet object.
+* 	@throw xap.xml.xmodify.XmodifyException
+*/
+xap.xml.xmodify.CommandDirective = function(directiveElement, session, directiveSet) {
+	
+	this._type = xap.xml.xmodify.UpdateDirective.getType(directiveElement.getLocalName());
+	this._commandArguments = directiveElement.childNodes;
+
+	this._nameAttr = directiveElement.getAttribute("name");
+	this._selectAttr = directiveElement.getAttribute("select");
+	this._cloneAttr = directiveElement.getAttribute("clone");
+	this._indexAttr = directiveElement.getAttribute("index");
+	
+	/* For mandatory arguments, like for set-attributes */
+	var argumentsException = xap.xml.xmodify.CommandDirective.checkArguments(this._type, this._commandArguments.length);
+	if(argumentsException !== null) { throw (argumentsException); }
+	
+	this._session = session; 
+	this._directiveSet = directiveSet;
 	this._log = xap.xml.xmodify.CommandDirective.s_log;
 	
-	/* Call our superclass' xap.xml.xmodify.UpdateDirective */
-	xap.xml.xmodify.UpdateDirective.call( this, elemDirectiveElement );  
+}; // end Constructor(...)
+
+
+
+//-----------------------------------------------------------------------
+//
+// 		Class Fields and Methods
+//
+//-----------------------------------------------------------------------
+
+
+/**
+ *
+ *	Establish a common instance of Logger.
+ *
+**/
+xap.xml.xmodify.CommandDirective.s_log = xap.log.Logger.getLogger( "xap.xml.xmodify.Xmodify" );
+
+
+/**
+ * Checks if the desired operation require a target node to work.
+ * @return true if this directive must have a target node.
+ * @param directiveType an integer from xap.xml.xmodify.UpdateDirective's 
+ * constants corresponding to our allowed operations (append, replace,...)
+ * @see xap.xml.xmodify.UpdateDirective#DIRECTIVE_NAMES
+**/
+xap.xml.xmodify.CommandDirective.isTargetExpected = function(directiveType)
+{
+    var result = (directiveType != xap.xml.xmodify.UpdateDirective.DIRECTIVE_CREATE_DOCUMENT);
+    return (result);
+};
+
+
+
+/**
+ * Checks if the desired operation has enough arguments (children of XModify directive) to work.
+ * @param directiveType an integer from xap.xml.xmodify.UpdateDirective's 
+ * constants corresponding to our allowed operations (append, replace,...)
+ * @param argumentsCount The number of children in the XModify directive.
+ * @return xap.xml.xmodify.XmodifyException if this directive does not has enough arguments to execute.
+ * @see xap.xml.xmodify.UpdateDirective#DIRECTIVE_NAMES
+**/
+xap.xml.xmodify.CommandDirective.checkArguments = function(directiveType, argumentsCount)
+{
+	if ((argumentsCount === 0) && 
+		(directiveType == xap.xml.xmodify.UpdateDirective.DIRECTIVE_SET_ATTRIBUTE)) {
+		return new xap.xml.xmodify.XmodifyException(
+			xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_ONE_ARG, "set-attribute") ;   
+	}
+    return (null);
+};
+
+
+/**
+*	Replaces an element with some other elements.
+*	The currentElement should have a valid parent.
+*
+* 	@param currentElement	DOM element to remove
+*	@param newElements		DOM elements to insert (can be empty)
+*/
+xap.xml.xmodify.CommandDirective.replaceElement = function(currentElement, newElements) {
+
+	// return if undefined or no parent
+	if( (!currentElement) || (!currentElement.parentNode) ) { return; }
 	
-	this._selectAttr = elemDirectiveElement.getAttribute("select");
-	this._commandArguments = elemDirectiveElement.childNodes ;
-	// Will set later, just before we execute this directive:
-	this._commandTargets = null ;
+	var parentElement = currentElement.parentNode;
+	var nextElement = currentElement.nextSibling;
 	
-	/* For mandatory arguments, like for set-attributes */
-	if ((this._commandArguments.length == 0) &&
-		(this._strType == "set-attribute") ) /* We'll replace this with a mustHaveArgs() func */
-	{
-		throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_ONE_ARG,"set-attribute") ;   
+	parentElement.removeChild(currentElement);
+	
+	var n = null;
+	
+	if(nextElement) {
+		for(n = 0; n < newElements.length; n++) { parentElement.insertBefore(newElements[n], nextElement); }
+	} else {
+		for(n = 0; n < newElements.length; n++) { parentElement.appendChild(newElements[n]); }
 	}
+
+}; // end replaceElement()
+
+
+
+/**
+*	Insert some other elements along with current element.
+*	This needs a valid parent in order to work.
+*
+* 	@param currentElement	DOM element
+*	@param newElements		DOM elements to insert
+*	@param isInsertBefore	True if insertBefore, False if insertAfter
+*/
+xap.xml.xmodify.CommandDirective.insertElement = function(currentElement, newElements, isInsertBefore) {
+
+	// return if undefined or no parent
+	if( (!currentElement) || (!currentElement.parentNode) ) { return; }
+	
+	var parentElement = currentElement.parentNode;
+	
+	var n = null;
+	
+	if(isInsertBefore) {
+		for(n = 0; n < newElements.length; n++) { parentElement.insertBefore(newElements[n], currentElement); }
+	} else {
+		// check if there is another node to use for insertBefore
+		if (currentElement.nextSibling) {
+			for(n = 0; n < newElements.length; n++) { parentElement.insertBefore(newElements[n], currentElement.nextSibling); }
+		} else {
+			// just straight append
+			for(n = 0; n < newElements.length; n++) { parentElement.appendChild(newElements[n]); }
+		}
+	} // end if(isInsertBefore)else
 	
-	this._session = session;  
-}
+}; // end insertElement()
+
+
+/**
+ * Selects the nodes in the document
+ * that match the select criteria given.
+ * @param uiDocument Target document
+ * @param selectString XPath select string
+ * @return Array containing matching nodes in target document
+ **/
+xap.xml.xmodify.CommandDirective.selectMatchingNodes = function(uiDocument, selectString) {
+ 
+    var targetNodesArray = [];
+    
+    // handle #ID syntax TODO: review this
+    // Do we still use/need #ID syntax?
+    if ( selectString && (selectString.charAt(0) == '#') ) {
+
+		var id = selectString.substring(1);
+	    var target = uiDocument.getElementById(id);
+		if(target) { targetNodesArray.push(target); }
+ 
+    } else {
+     
+    	var parsedXPathExpr = google.xpathParse(selectString);
+    	var currentContext = new google.ExprContext(uiDocument);
+    	var targetNodes = parsedXPathExpr.evaluate(currentContext);
+    	targetNodesArray = targetNodes.nodeSetValue();
+    		
+	} // end if()
+	
+    return targetNodesArray;
+};
+
+
+//-----------------------------------------------------------------------
+//
+// 		Public methods. (Publc instance methods)
+//
+//-----------------------------------------------------------------------
 
-xap.xml.xmodify.CommandDirective.s_log = xap.log.Logger.getLogger( "xap.xml.xmodify.Xmodify" );
 
 /**
  * Executes this command directive against the passed-in context node---
  * First find the targets of the operation on construction, then execute
  * the callback corresponding to the directive.
- * @param uiDocumentNode The UI document, presumably including nodes that 
- * will be selected to be the object of the directive.
+ * @param uiDocument The UI document, presumably including nodes that will be selected to be the object of the directive.
+ * @param baseUrl
  * @throws xap.xml.xmodify.XmodifyException
  */
-xap.xml.xmodify.CommandDirective.prototype.execute = function (uiDocumentNode, baseUrl)
+xap.xml.xmodify.CommandDirective.prototype.execute = function (uiDocument, baseUrl)
 {
-    this._commandTargets 
-        = this._selectMatchingNodes(uiDocumentNode,this._selectAttr ) ;
-
-    var directiveType 
-        = xap.xml.xmodify.UpdateDirective.getDirectiveTypeAsInt(this._strType) ;
-    
-    this._bHtmlDocument = !(uiDocumentNode instanceof xap.xml.dom.Document);   
+    var commandTargets = xap.xml.xmodify.CommandDirective.selectMatchingNodes(uiDocument, this._selectAttr) ;
+    var isXapDocument = (uiDocument instanceof xap.xml.dom.Document); 
         
-    // handle "no targets" case---
-    var needsTarget = xap.xml.xmodify.CommandDirective._mustHaveTarget(directiveType) ;
-    
-    //if we need a target and don't have one log a message and continue
-    if ( needsTarget && ( this._commandTargets.length == 0 ) ){
-    	if (this._log.isDebug()){
-			this._log.debug(xap.util.XapException.exceptionToString(
-				new xap.xml.xmodify.XmodifyException(
-					xap.xml.xmodify.XmodifyException.ZERO_RESULTS, 
-					this._selectAttr)
-					));
-    	}
+    // if we need a target and don't have one log a message and return
+    if ( (commandTargets.length === 0) && xap.xml.xmodify.CommandDirective.isTargetExpected(this.getType()) ) {
+	    var ex = new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.ZERO_RESULTS, this._selectAttr);
+		if(this._log.isDebug()) { this._log.debug(xap.util.XapException.exceptionToString(ex)); }
 		return;
     }
-        
-    /* @TODO: Switch on type, use ints, not strs */
-    switch (directiveType) {
+    	
+    // select and call the modification handler
+	switch (this.getType()) {
+        case xap.xml.xmodify.UpdateDirective.DIRECTIVE_VARIABLE:
+		  this._handleVariable(uiDocument, commandTargets, (this._cloneAttr && this._cloneAttr == 'true'));
+		  break;
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_APPEND:
-		  this._handleAppend(uiDocumentNode);
+		  this._handleAppend(uiDocument, commandTargets);
 		  break;
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_SET_ATTRIBUTE:
-		  this._handleSetAttribute(uiDocumentNode, baseUrl);
+		  this._handleSetAttribute(uiDocument, baseUrl, commandTargets);
 		  break;
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_ELEMENT:
-		  this._handleRemoveElement(uiDocumentNode);
+		  this._handleRemoveElement(uiDocument, commandTargets);
 		  break;
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_ATTRIBUTE:
-		  this._handleRemoveAttribute(uiDocumentNode);
+		  this._handleRemoveAttribute(uiDocument, commandTargets);
           break;     
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_INSERT_BEFORE: 
-		  this._handleInsertBefore(uiDocumentNode);
+		  this._handleInsert(uiDocument, commandTargets, true);
 		  break;   
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_INSERT_AFTER: 
-          this._handleInsertAfter(uiDocumentNode);
+          this._handleInsert(uiDocument, commandTargets, false);
+          break;                
+        case xap.xml.xmodify.UpdateDirective.DIRECTIVE_INSERT_AT: 
+          this._handleInsertAt(uiDocument, commandTargets);
           break;                
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_REPLACE: 
-          this._handleReplace(uiDocumentNode);
-          break;   
-        case xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_CHILDREN: 
-          this._handleRemoveChildren(uiDocumentNode);
-          break;   
+          this._handleReplace(uiDocument, commandTargets);
+          break;
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_REPLACE_CHILDREN: 
-          this._handleReplaceChildren(uiDocumentNode);
-          break; 
+          this._handleReplaceChildren(uiDocument, commandTargets);
+          break;           
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_CLONE: 
-          this._handleClone(uiDocumentNode);
-          break;                            	                               
+          this._handleClone(uiDocument, commandTargets);
+          break;
+        // NOTE: the following is not in the API
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_EMBED_XAL: 
-          this._handleEmbedXal(uiDocumentNode);
+          this._handleEmbedXal(uiDocument, commandTargets);
           break;                            	                               
         case xap.xml.xmodify.UpdateDirective.DIRECTIVE_SET_INNER_HTML: 
-          this._handleSetInnerHtml(uiDocumentNode);
-          break;                            	                               
-        default: 
-	       if (this._log.isDebug()) this._log.debug("Unhandled command : "+this._strType);
+          this._handleSetInnerHtml(uiDocument, commandTargets);
+          break;
+        default:
+        	if (this._log.isDebug()) {
+	          var message = xap.util.MessageFormat.format("Unhandled command : {0}", [this.getType()]);
+		      this._log.debug(message);
+		    }
     } /* end switch */
-} /* end execute */
-
+    
+}; /* end execute() */
 
 
 /**
- * Does the desired operation require a target node to work?
- * @return true if this directive must have a target node.
- * @param nDirectiveType an integer from xap.xml.xmodify.UpdateDirective's 
- * constants corresponding to our allowed operations (append, replace,...)
- * @see xap.xml.xmodify.UpdateDirective#DIRECTIVE_NAMES
+ * Creates a temporary variable to hold the set of nodes for use in <xm:value-of name='...'> element.
+ * Makes this variable available for all subsequent <xm:value-of> directives.
+ * @param uiDocument {Document} Target document.
+ * @param targetNodes {Element} Target nodes in uiDocument.
+ * @param needClone {Boolean} Clone flag
+ * @throw xap.xml.xmodify.XmodifyException
 **/
-xap.xml.xmodify.CommandDirective._mustHaveTarget = function(nDirectiveType){
-//Don't need target for create-document...any others?
-    var needs = (nDirectiveType != xap.xml.xmodify.UpdateDirective.DIRECTIVE_CREATE_DOCUMENT) ;
-    return needs ;
-
-}
+xap.xml.xmodify.CommandDirective.prototype._handleVariable = function(uiDocument, targetNodes, needClone)
+{
+	// check if we have a name
+	if(!this._nameAttr) {
+		this._log.debug("Variable element requires a name.");
+		return;
+	}
+	
+	// create variables property in parent
+	if(!this._directiveSet.variables) {
+		this._directiveSet.variables = {};
+	}
+	
+	var myVar = [];
 
+	// copy target nodes
+	for(var n = 0; n < targetNodes.length; n++) {
+		var currentNode = targetNodes[n];
+	    this._log.debug('Variable node: ' + currentNode.nodeName);
+		myVar.push(currentNode); 
+	} // end for n.. 
 
-/**
- * @private
- * Select the nodes in the document
- * that match the select criteria given.
- **/
-xap.xml.xmodify.CommandDirective.prototype._selectMatchingNodes = function(uiDocumentNode,selectString){
- 
-    var targetNodesArray= new Array(0) ;
-    var localSelectString = selectString ;
- 
-    
-    //handle #ID syntax
-    //TODO document this
-    if ( selectString && selectString.charAt(0)=='#'){
-		var id = selectString.substring(1);
-	   var target = uiDocumentNode.getElementById(id);
-		if( target && typeof target != "undefined"){
-			targetNodesArray.push(target) ;	
-		}
-    
-    } else {
-    	var currentContext =   new google.ExprContext(uiDocumentNode) ;
-    	var parsedXPathExpr = google.xpathParse(localSelectString) ;
+	// save "clone" flag
+	myVar.needClone = needClone;
 	
-    	var targetNodes = parsedXPathExpr.evaluate( currentContext );
-    	var targetNodesArray = targetNodes.nodeSetValue();	
-    }
+	// update parent's list of variables
+	this._directiveSet.variables[this._nameAttr] = myVar;
 	
-    return targetNodesArray ;
-}
+}; // end _handleVariable
 
 
 /**
- * Appends the nodes held in <code>this._commandArguments</code> to the nodes held in
- * <code>this._commandTargets</code>.
+ * Appends the nodes held in  <code>this._commandArguments</code> to the nodes held in  <code>targetNodes</code>.
+ * @param uiDocument {Document} Target document.
+ * @param targetNodes {Element []} Target nodes in uiDocument.
  * @throw xap.xml.xmodify.XmodifyException
 **/
-xap.xml.xmodify.CommandDirective.prototype._handleAppend = function(uiDocumentNode)
+xap.xml.xmodify.CommandDirective.prototype._handleAppend = function(uiDocument, targetNodes)
 {
-    var targetNodes = this._commandTargets ;
-    var elemsToAppend = this._commandArguments;      
-    if (this._log.isDebug())
-	    this._log.debug (
-				 "We have " 
-				 + elemsToAppend.length 
-				 + " children  to append to " 
-				 + this._selectAttr 
-				 + ": " 
-				 + this.formatDocument(uiDocumentNode)
-				 );
-  							
-    for (var i = 0; i < targetNodes.length ; i ++)
-    {
-
-	/* Must CLONE elemsToAppend - otherwise elemsToAppend.length changes 
-	 * while in loop..
-	 */
-
-	var currentNode = targetNodes[i];
-	if (currentNode.nodeType == google.DOM_DOCUMENT_NODE ){
-		if (elemsToAppend.length != 1)
-		    {
-			throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.SET_ROOT_ELEMENT_EXPECTS_ONE_ARG);
-		    }
+    var elemsToAppend = this._commandArguments;
+       
+    if (this._log.isDebug()) {
+    	var message1 = xap.util.MessageFormat.format("We have {0} children to append to {1}:{2}", 
+			[elemsToAppend.length, this._selectAttr, this.formatDocument(uiDocument)]);
+	    this._log.debug(message1);
+  	}
+  	
+    for(var i = 0; i < targetNodes.length; i++) {
+
+		var currentNode = targetNodes[i];
 		
-		if (this._log.isDebug())
-			this._log.debug (
-			"We have 1 elem to append as new root : " 
-			+ elemsToAppend[0]
-			);
-		currentNode.setRootElement(elemsToAppend[0]);
-         
-    } else if (currentNode.nodeType == google.DOM_ELEMENT_NODE ){
-		for (var j = 0; j < elemsToAppend.length; j++){
-			try {
-                 if (currentNode instanceof google.XNode){
-			        currentNode.appendChild(elemsToAppend[j].deepClone()); 
-                 } else if (this._bHtmlDocument){
-			        currentNode.appendChild(this.makeNodeHTML(elemsToAppend[j])); 
-			     }
-			} 
-			catch (e) { 
-			    if (e.toString().indexOf('MsgId:idConflict')!= -1)
-				{
-				    alert("rethrowing exception");
-				    throw (e);
-				}
-			    else
-				{
-				    xap.xml.xmodify.CommandDirective.s_log.debug ("Exception: " + e + " This could be because of a duplicate id issue despite deepClone"); }
+		if (currentNode.nodeType == google.DOM_DOCUMENT_NODE ) {
+		
+			if (this._log.isDebug()) {
+				this._log.debug ("We have 1 elem to append as new root : " + elemsToAppend[0]);
+			}
+		
+			if (elemsToAppend.length != 1) {
+				throw new xap.xml.xmodify.XmodifyException(
+					xap.xml.xmodify.XmodifyException.SET_ROOT_ELEMENT_EXPECTS_ONE_ARG);
+			} else {
+				currentNode.setRootElement(elemsToAppend[0]);
+				return;
 			}
-		    } ;/* end for j.. */
+			
+    	} else if (currentNode.nodeType == google.DOM_ELEMENT_NODE ) {
+    	
+			for(var j = 0; j < elemsToAppend.length; j++) {
+				try {
+					var nodesToAppend = this._createNode(uiDocument, elemsToAppend[j]);
+					var message2 = xap.util.MessageFormat.format('Appending {0} nodes to {1}',
+						[nodesToAppend.length, currentNode.nodeName]);
+					this._log.debug(message2);
+					for(var k = 0; k < nodesToAppend.length; k++) {
+						currentNode.appendChild(nodesToAppend[k]);
+					}
+				} catch (e) { 
+				   if(this._log.isDebug()) { this._log.debug ("Exception: " + e.message); }
+				}
+			} // end for j.. 
 
-	    } /* end if Element */
-          else {
-		      throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANT_BLANK_TO_NODE_TYPE, "append", currentNode.nodeType) ;
+	    } else  { // if(currentNode.nodeType)
+			throw new xap.xml.xmodify.XmodifyException(
+		      	xap.xml.xmodify.XmodifyException.INVALID_NODE_FOR_COMMAND, currentNode.nodeType, "append");
         }
-    } /* end for i < targetNodes.length...*/
-
-	if (this._log.isDebug())
-	    this._log.debug("Post Append uIDoc: \n " 
-				+ this.formatDocument(uiDocumentNode) 
-				);
+        
+    } // end for( i < targetNodes.length...)
 
+};  /* end handleAppend */
 
 
-}  /* end handleAppend */
 
 
 /**
  * Sets attributes of the nodes held in <code>this._commandArguments</code> 
- * according to the name/value pairs held as attributes in
- * <code>this._commandTargets</code>, e.g. &lt;xm:set-attribute name=&quot;width&quot; value=&quot;30px&quot;/&gt;
+ * according to the name/value pairs held as attributes in <code>targetNodes</code>,
+ * e.g. &lt;xm:set-attribute name=&quot;width&quot; value=&quot;30px&quot;/&gt;
+ * @param uiDocument {Document} Target document.
+ * @param baseUrl {String} Base URL.
+ * @param targetNodes {Element []} Target nodes in uiDocument.
  * @throws xap.xml.xmodify.XmodifyException
 **/
-xap.xml.xmodify.CommandDirective.prototype._handleSetAttribute = function(uiDocumentNode, baseUrl)
+xap.xml.xmodify.CommandDirective.prototype._handleSetAttribute = function(uiDocument, baseUrl, targetNodes)
 {
 
-    /* @TODO: Validity checks */
-    var attrsToSet = this._commandArguments;
-    var targetNodes = this._commandTargets ;
-
-    if (!targetNodes.length){
-        /* Throw an exception? Alert? */
+	// check if we have targets
+    if ( (!targetNodes.length) || (targetNodes.length === 0) ){
+    	throw new xap.xml.xmodify.XmodifyException(
+       		xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_TARGETS, "set-attribute");
     }
 
-    for (var i = 0; i < targetNodes.length; i ++){
-        var currentNode = targetNodes[i];
+    var attributes = this._commandArguments;
 
-        if (currentNode.nodeType == google.DOM_ELEMENT_NODE  ){
-			for (var j = 0 ; j < attrsToSet.length; j++){
-		    	try {             
-					var attrToSet = attrsToSet[j];
-					if (attrToSet.getLocalName 
-			    		// a little roundabout, just a way of seeing if the node local
-			    		// name is "attribute"
-			    		&& xap.xml.xmodify.UpdateDirective.getDirectiveTypeAsInt(attrToSet.getLocalName()) == xap.xml.xmodify.UpdateDirective.DIRECTIVE_ATTRIBUTE 
-                      ){              
-						var name = attrToSet.getAttribute('name');
-						var val = attrToSet.getAttribute('value');
-						currentNode.setAttribute(name, val, baseUrl);
-			    	} else {
-			    		throw new xap.xml.xmodify.XmodifyException(
-			    				xap.xml.xmodify.XmodifyException.ATTRIBUTE_ARGUMENT_NOT_ATTRIB_DIRECTIVE, 
-			    				attrToSet.getLocalName()
-			    				);
-					}
+    for(var i = 0; i < targetNodes.length; i++) {
+    
+        var currentNode = targetNodes[i];
 
-		    	} catch (e) { alert(j + " " + e.message); }
+        if(currentNode.nodeType == google.DOM_ELEMENT_NODE) {
+        
+			for(var j = 0; j < attributes.length; j++) {
+			
+				var attribute = attributes[j];
+
+		    	/* check to see if it is, in fact, an attribute */
+				if( attribute.getLocalName && (attribute.getLocalName() == 
+					xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_ATTRIBUTE]) ) {              
+					var name = attribute.getAttribute('name');
+					var value = attribute.getAttribute('value');
+					currentNode.setAttribute(name, value, baseUrl);
+		    	} else {
+		    		throw new xap.xml.xmodify.XmodifyException(
+		    			xap.xml.xmodify.XmodifyException.ATTRIBUTE_ARGUMENT_NOT_ATTRIB_DIRECTIVE, 
+		    			attribute.nodeName);
+				}
 
-		} /* end for */
-	}
-	else
-	{
-            throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANT_BLANK_TO_NODE_TYPE, "Set-Attribute", currentNode.nodeType) ;
-	}
-    }; /* End for */
+			} /* end for */
+		} else	{
+			throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.INVALID_NODE_FOR_COMMAND, currentNode.nodeType, "set-attribute") ;
+		}
+    } /* End for */
 
-	if (this._log.isDebug())
-		this._log.debug("Post Set-Attr: \n " + this.formatDocument(uiDocumentNode) );
- 
-} /* end handleSetAttribute */
+}; /* end handleSetAttribute */
 
 
+/**
+ *
+ * Replaces children of targetNodes with commandArguments.
+ * If commandArguments is empty, then it just removes children. 
+ *
+ *
+ * @param uiDocument {Document} Target document.
+ * @param targetNodes {Element} Target nodes in uiDocument.
+ * @throw xap.xml.xmodify.XmodifyException
+*/
+xap.xml.xmodify.CommandDirective.prototype._handleReplaceChildren = function(uiDocument, targetNodes)
+{
 
-xap.xml.xmodify.CommandDirective.prototype._handleReplaceChildren = function(uiDocumentNode){
-	var targetNodes = this._commandTargets ;
-	var elemsToAppend = this._commandArguments; 
+	var elements = this._commandArguments; 
 	
-	//IMPORTANT if we get an exception what is the right granularity to continue??
-	for (var i=0; i<targetNodes.length; i++){
-		var elem = targetNodes[i];
+	for(var i = 0; i < targetNodes.length; i++){
+	
+		var node = targetNodes[i];
  		
  		//if it is not an element you can't replace the children
  		//technically document could allow this too...
- 		if (elem.nodeType!=google.DOM_ELEMENT_NODE){
+ 		if (node.nodeType != google.DOM_ELEMENT_NODE){
  			continue;
  		}
  		
  		//remove each child
- 		while(elem.childNodes.length>0){
- 			elem.removeChild(elem.childNodes[0]);
+ 		while(node.childNodes.length > 0) {
+ 			node.removeChild(node.childNodes[0]);
  		}
  		
- 		//then stick on the new ones
- 		for (var j = 0; j < elemsToAppend.length; j++){
-			if (elem instanceof google.XNode){
-	      		elem.appendChild(elemsToAppend[j].deepClone()); 
-         	} else if (this._bHtmlDocument){
-	        	elem.appendChild(this.makeNodeHTML(elemsToAppend[j])); 
-	     	}
+ 		//then stick on the new ones if there are any
+ 		for(var j = 0; j < elements.length; j++){
+ 			var replacementNodes = this._createNode(uiDocument, elements[j]);
+ 			for(var k = 0; k < replacementNodes.length; k++) {
+      			node.appendChild(replacementNodes[k]);
+      		}
  		}
  	}
-}
+};
 
 /**
- * Removes the nodes held in <code>this._commandArguments</code> (and 
- * their subtrees, if any).
+ * Removes the nodes held in <code>targetNodes</code> (and their subtrees, if any).
+ * @param uiDocument {Document} Target document.
+ * @param targetNodes {Element} Target nodes in uiDocument.
  * @throw xap.xml.xmodify.XmodifyException
 **/
-xap.xml.xmodify.CommandDirective.prototype._handleRemoveElement = function(uiDocumentNode)
+xap.xml.xmodify.CommandDirective.prototype._handleRemoveElement = function(uiDocument, targetNodes)
 {
-    /** Removing an element from the XPATH specified  **/
-    var xpathRemoved = this._selectAttr;
-    var targetNodes = this._commandTargets ;  
+	// check if we have targets to remove
+    if ( (!targetNodes.length) || (targetNodes.length === 0) ){
+    	throw new xap.xml.xmodify.XmodifyException(
+       		xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_TARGETS, "remove");
+    }
 
-	if (this._log.isDebug())
-		this._log.debug('removing the element at XPath : ' 
-            + xpathRemoved + " Results: " 
-            + targetNodes.length
-            );
+	/** Removing an element from the XPATH specified  **/
+    var xpathRemoved = this._selectAttr;
 
+	if (this._log.isDebug()) {
+		var message1 = xap.util.MessageFormat.format('Removing the element at XPath {0} : results : {1}',
+			[xpathRemoved, targetNodes.length]);
+		this._log.debug(message1);
+	}
 
-    try{
-    for (var i = 0; i < targetNodes.length ; i ++)
-        {
-        /* 2DO: Handle text nodes */
-        var elem = targetNodes[i];
+	for(var i = 0; i < targetNodes.length ; i++) {
    
-        if (!elem) 
-            {
-            /* Could be null - e.g. if a firstTextChild did not exist -
-             * in which case, we just continue.. 
-             */
-            continue;
-            }
-  
-        /* This may issue #1 - I return getFirstTextChild - that's good.
-           BUT, I can't getClass on it to have it return "Text". in fact, it
-           DOES show me the text content, but getClass is not defined.. 
-           I can't use getParent either.. although in the Java code you do both.
-           I assume it's a string. Can I simply use setFirst.. instead?
-        */
-         if (elem.nodeType == google.DOM_ELEMENT_NODE)
-            {
-            var parent = elem.parentNode;
-
-            if (parent)
-                {
-                parent.removeChild(elem);
-                }
-            else
-                { /* Parent is NULL - remove document altogether !*/
-                uiDocumentNode.setRootElement(null);
-                }
-            }
-        else if (elem.nodeType == google.DOM_TEXT_NODE)
-            {
-            xap.xml.xmodify.CommandDirective.s_log.debug ("Removing text node: "+elem.nodeValue());
-            var parent = elem.parentNode;
-            if (parent)
-                {
-                parent.removeChild(elem.getFirstTextChild());
-                }
-            }
-        else { alert ("element " + elem.nodeType + " not supported");
-                throw ("element " + elem.nodeType + " not supported");
-        }
+		var element = targetNodes[i];
+	
+        /* Could be null (?) In which case, we just continue.. */
+       	if(!element) { continue; }
+      	
+      	// Currently only DOM_ELEMENT_NODE and DOM_TEXT_NODE element supported
+      	switch(element.nodeType) {
+      	
+      		case(google.DOM_ELEMENT_NODE):
+          		if (element.parentNode) { 
+         			element.parentNode.removeChild(element);
+	        	} else if (element === uiDocument.getRootElement() ) {
+	            	/* Parent is NULL - remove document altogether and return! */
+	              	uiDocument.setRootElement(null);
+	              	return;
+	            } else {
+	              	// element has no parent -- do nothing
+	            }
+	      		break;
+	      		
+      		case(google.DOM_TEXT_NODE):
+				var message2 = xap.util.MessageFormat.format('Removing text node ({0})', [element.nodeValue()]);
+				if(this._log.isDebug()) { this._log.debug (message2); }
+	          	if (element.parentNode) { element.parentNode.removeChild(element); }
+	      		break;
+	      		
+      		default:
+      			throw new xap.xml.xmodify.XmodifyException(
+      				xap.xml.xmodify.XmodifyException.INVALID_NODE_FOR_COMMAND, element.nodeName, 'remove-element');
 
-        }; /* end for */
+      	}// end switch()
 
-    } catch (e) {alert(e.message);}
-    if (this._log.isDebug())
-        this._log.debug("Post Remove: " + this.formatDocument(uiDocumentNode));
+	} /* end for */
 
-} /* end handleRemove */
+}; /* end _handleRemoveElement */
 
-/**
- * Removes all the children for a given node---simpler than remove-element,
- * since that one must handle text nodes specially, and contend with the 
- * possibility that an element to be removed has no parent to remove it.
- * @see xap.xml.xmodify.CommandDirective#_handleRemoveElement
- * @throws xap.xml.xmodify.XmodifyException
- * @param uidDocument---complete xml for the layout, to date also includes the
- * specs for the modification directives handles by this class's instances....
- * @author mturyn
-**/
-xap.xml.xmodify.CommandDirective.prototype._handleRemoveChildren = function(uiDocumentNode){
-//xap.xml.xmodify.Xmodify.DEBUG=true;
-    /** Removing an element from the XPATH specified  **/
-    var parentSelector = this._selectAttr;
-    var targetNodes = this._commandTargets ;  
-
-	if (this._log.isDebug())
-	    this._log.debug('Removing the children of nodes for XPath : ' 
-		    + parentSelector + " Results: " 
-		    + targetNodes.length
-		    );
-
-
-    try{
-        for (var i = 0; i < targetNodes.length ; i ++){
-            var currentParent = targetNodes[i];
-
-            if (!currentParent){
-                /* Could be null - e.g. if a firstTextChild did not exist -
-                * in which case, we just continue.. 
-                */
-                continue;
-            }
-
-            // If no children, no operation:
-            if ( currentParent.childNodes == null
-                || currentParent.childNodes.length==0
-                    ){
-                continue ;
-            }
-            var lastIndex = currentParent.childNodes.length ;
-            // childNodes will shrink with each removal:
-            while(--lastIndex > -1 ){
-                var currentChild = currentParent.childNodes[lastIndex] ;
-                currentParent.removeChild(currentChild) ;
-            } // end loop over all children to remove for a given parent
-        } // end loop over all parents selected
-
-    } catch (e) {
-        alert(e.message);
-    } 
-    if (this._log.isDebug())
-		this._log.debug("Post Remove: " + this.formatDocument(uiDocumentNode));       
-
-} /* end _handleRemoveChildren */
 
 
 /**
  * Removes the attributes specified by <code>this._commandArguments</code> from the
- * nodes in <code>this._commandTargets</code> 
- * @throws xap.xml.xmodify.XmodifyException
- * @param uidDocument---complete xml for the layout, to date also includes the
+ * nodes in <code>targetNodes</code> 
+ * @param uidDocument Complete xml for the layout, to date also includes the
  * specs for the modification directives handles by this class's instances....
+ * @param targetNodes Nodes to remove attributes from
+ * @throws xap.xml.xmodify.XmodifyException
  * @author mturyn
 **/
-xap.xml.xmodify.CommandDirective.prototype._handleRemoveAttribute = function(uiDocumentNode){
+xap.xml.xmodify.CommandDirective.prototype._handleRemoveAttribute = function(uiDocument, targetNodes)
+{
+    if ( (!targetNodes.length) || (targetNodes.length === 0) ){
+       throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_TARGETS, "remove-attriute");
+    }
 
-    /* @TODO: Validity checks */
-    var attrsToRemove = this._commandArguments ;
-    var targetNodes = this._commandTargets ;  
+    var attributes = this._commandArguments;
 
-	if (this._log.isDebug())
-		this._log.debug("Pre Remove-Attr: "+this._selectAttr+"\n " + this.formatDocument(uiDocumentNode) );
+    for(var i = 0; i < targetNodes.length; i++) {
 
-    for (var i = 0; i < targetNodes.length ; i ++){
         var currentNode = targetNodes[i];
 
-        if (currentNode.nodeType == google.DOM_ELEMENT_NODE){
-            for (var j = 0 ; j < attrsToRemove.length ; j++) {
-                try {
-             
-              var attrToRemove = attrsToRemove[j];
-              if (attrToRemove.getLocalName 
-               // a little roundabout, just a way of seeing if the node local
-               // name is "attribute"
-               && (xap.xml.xmodify.UpdateDirective.getDirectiveTypeAsInt(attrToRemove.getLocalName()) 
-                   == xap.xml.xmodify.UpdateDirective.DIRECTIVE_ATTRIBUTE 
-                   )
-               ){             
-               var name = attrToRemove.getAttribute('name');
-               currentNode.removeAttribute(name);
-              } else {
-                throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.ATTRIBUTE_ARGUMENT_NOT_ATTRIB_DIRECTIVE, attrToSet.getLocalName());
-              }
-
-          } catch (e) { alert(j + " " + e.message); }
-
-         } // (End iterating over nodes from which to remove attribute[s].)
-     }   // This was an element
-     else {
-         throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANT_BLANK_TO_NODE_TYPE, "Set-Attribute", currentNode.nodeType) ;
-     }
-    }; // (End iterating over attribute[s] to remove.)
-
-    if (this._log.isDebug())
-		this._log.debug("Post Remove-Attr: \n " + this.formatDocument(uiDocumentNode) );
- 
-} /* end handleRemoveAttribute */
-
-
-
-
-
-/**
- * A helper method for the <code>insert-before</code>  
- * and <code>insert-after</code>  directives:
- * @deprecated
- * @param index
- * @param parent
- * @param contextNode
- * @throws xap.xml.xmodify.XmodifyException
- */
-xap.xml.xmodify.CommandDirective.prototype.insertCommandArgumentsAt 
-    = function(index,parent,contextNode, xpathResultIndex)
-{
-	var arrArguments = this._commandArguments ;
-    for (var ii=0; ii<arrArguments.length; ++ii ) {
+        if (currentNode.nodeType == google.DOM_ELEMENT_NODE) {
+        
+            for(var j = 0; j < attributes.length; j++) {
+            
+              	var attribute  = attributes[j];
+              
+		    	/* check to see if it is, in fact, an attribute */
+				if( attribute.getLocalName && (attribute.getLocalName() == 
+					xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_ATTRIBUTE]) ) {              
+					var name = attribute.getAttribute('name');
+					currentNode.removeAttribute(name);
+		    	} else {
+		    		throw new xap.xml.xmodify.XmodifyException(
+		    			xap.xml.xmodify.XmodifyException.ATTRIBUTE_ARGUMENT_NOT_ATTRIB_DIRECTIVE, 
+		    			attribute.nodeName);
+				}              
+              
+         	} // (End iterating over nodes from which to remove attribute)
+         
+	     } else {
+	         throw new xap.xml.xmodify.XmodifyException(
+	         	xap.xml.xmodify.XmodifyException.INVALID_NODE_FOR_COMMAND, "remove-attribute", currentNode.nodeType);
+	     }
+	     
+    } // (End iterating over attribute[s] to remove)
 
-	// unresolved argument: (arbitrary xml | String | CloneDirective |
-	// ValueOfDirective)*
-	var arg = arrArguments[ii] ;
-	// Just try it for XNode and descendants so far:
-	if (arg instanceof google.XNode){
-		parent.insertChildAt(index, arg);
-	} else {
-		throw new xap.xml.xmodify.XmodifyException("Can't insert the desired element, can only insert XNode (or descendant) instances so far.") ;
-	}	
-	
-	
-	
-/*
-	if (arg instanceof xap.xml.xmodify.CommandDirective) {
-	    var resolvedArgs = this.evaluateArgumentDirective(
-							    arg, contextNode, environment);
-	    if (resolvedArgs != null) {
-		for (var e2 = resolvedArgs.elements(); e2.hasMoreElements();) {
-		    var resolvedArg = e2.nextElement();
-
-		    if (resolvedArg instanceof Element) {
-				parent.insertChildAt(index, resolvedArg);
-				index++;
-		    } else if (resolvedArg instanceof String) {
-				parent.insertChildAt(index, resolvedArg);
-				index++;
-		    } else {
-				parent.insertChildAt(index, resolvedArg.toString());
-				index++;
-		    }
-		}
-	    }
-	} else {
-	    if (arg instanceof Element) {
-		if (xpathResultIndex > 0) {
-		    var copy = this.cloneElementWithClientServerIdMatching(
-									  arg, true, // deep
-									  false // withIds
-											);
-		    parent.insertChildAt(index, copy);
-		} else {
-		    parent.insertChildAt(index, arg);
-		}
-		index++;
-	    } else if (arg instanceof String) {
-			parent.insertChildAt(index, arg);
-			index++;
-	    } else {
-			parent.insertChildAt(index, arg.toString());
-			index++;
-	    }
+    if (this._log.isDebug()) {
+		this._log.debug("Completed remove-attribute: " + this.formatDocument(uiDocument) );
 	}
-	*/
-    } // End of for() loop over elements to append in
-}
-
+ 
+}; /* end _handleRemoveAttribute() */
 
 
 
 /**
- * A helper method to for the <code>insert-before</code>  directive:
+ * A helper method to for the <code>insert-before</code> and
+ * <code>insert-after</code> directives:
  * 
- * @param contextNode
+ * @param uiDocument		Target document
+ * @param targetNodes		Target nodes
+ * @param isInsertBefore	Toggles between insertBefore and insertAfter
  * @throws xap.xml.xmodify.XmodifyException
  */
-xap.xml.xmodify.CommandDirective.prototype._handleInsertBefore = function(contextNode){
+xap.xml.xmodify.CommandDirective.prototype._handleInsert = function(uiDocument, targetNodes, isInsertBefore)
+{
 
-    /* @TODO: Validity checks */
-    var targetNodes = this._commandTargets ;  
+ 	var replacementNodes = this._commandArguments;
 
- 
-    for (var i = 0; i < targetNodes.length ; i ++){
-        var currentNode = targetNodes[i] ;
-        var parent = null ;
-        var index = -1 ;
-
-        parent = currentNode.parentNode ;
-
-        if (currentNode.nodeType == google.DOM_ELEMENT_NODE ||
-         	currentNode.nodeType == google.DOM_TEXT_NODE) {
-            if ( parent == null ) {
-                throw new xap.xml.xmodify.XmodifyException(
-                        xap.xml.xmodify.XmodifyException.INVALID_INSERT_AFTER_BECAUSE_OF_PARENT, 
-                        "'undefined'");
-            }
-        } else if (currentNode.nodeType == google.DOM_ATTRIBUTE_NODE) {
-            //TODO we might want to make it work in the future.
-            // to make it work for attributes we'll need additional
-            // API on the Element: setAttributeAt
-            throw new xap.xml.xmodify.XmodifyException(
-                        xap.xml.xmodify.XmodifyException.CHILDREN_CANT_BE_ADDED, 
-                        parent.nodeName); 
-        } else {
-            throw new xap.xml.xmodify.XmodifyException(
-                    xap.xml.xmodify.XmodifyException.INVALID_INSERT_BEFORE_BECAUSE_OF_PARENT,
-                    currentNode.nodeName);
+    for(var i = 0; i < targetNodes.length; i++) {
+    
+        var currentNode = targetNodes[i];
+        var nodesArray = [];
+        
+        // skip undefined or parentless nodes
+        if( (!currentNode) || (!currentNode.parentNode) )  {
+        	this._log.debug("Node undefined or does not have a parent node"); 
+        	continue; 
+        }
+        
+        // skip attribute nodes
+        if ( currentNode.nodeType == google.DOM_ATTRIBUTE_NODE ) {
+   			this._log.debug("Can't insert non-attribute node before an attribute node"); 
+   			continue; 
         }
-
-        // Do the simple thing, at this point:
-        if (this._log.isDebug())
-			this._log.debug("Pre insert-before: <" + currentNode.nodeName+"/>:\n" + this.formatDocument(parent));
         
-        this._insertCommandArgumentsBefore(parent,currentNode) ;
-
-	if (this._log.isDebug())
-		this._log.debug("Post insert-before:  <" + currentNode.nodeName+"/>:\n" + this.formatDocument(parent) );
-
-
-        //this.insertCommandArgumentsAt(index, parent, contextNode, i);
-    }
-
-}
-
-/**
- * A helper method to for the <code>insert-after</code>  directive:
- * 
- * @param contextNode
- * @throws xap.xml.xmodify.XmodifyException
- */
-xap.xml.xmodify.CommandDirective.prototype._handleInsertAfter = function(contextNode){
-
-    /* @TODO: Validity checks */
-    var targetNodes = this._commandTargets ;  
  
-    for (var i = 0; i < targetNodes.length ; i ++){
-        var currentNode = targetNodes[i] ;
-        var parent = null ;
-        var index = -1 ;
-
-        parent = currentNode.parentNode ;
-
-        if (currentNode.nodeType == google.DOM_ELEMENT_NODE ||
-         	currentNode.nodeType == google.DOM_TEXT_NODE) {
-            if ( parent == null ) {
-                throw new xap.xml.xmodify.XmodifyException(
-                        xap.xml.xmodify.XmodifyException.INVALID_INSERT_AFTER_BECAUSE_OF_PARENT, 
-                        "'undefined'"
-                            )
-            }
-        } else if (currentNode.nodeType == google.DOM_ATTRIBUTE_NODE) {
-            //TODO we might want to make it work in the future.
-            // to make it work for attributes we'll need additional
-            // API on the Element: setAttributeAt
-            throw new xap.xml.xmodify.XmodifyException(
-                        xap.xml.xmodify.XmodifyException.CHILDREN_CANT_BE_ADDED, 
-                        parent.nodeName 
-                            ) ; 
-        } else {
-            throw new xap.xml.xmodify.XmodifyException(
-                    xap.xml.xmodify.XmodifyException.INVALID_INSERT_BEFORE_BECAUSE_OF_PARENT,
-                    currentNode.nodeName
-                                        ) ;
+       	if (currentNode.nodeType == google.DOM_ELEMENT_NODE || currentNode.nodeType == google.DOM_TEXT_NODE) {
+       	
+       		for(var j = 0; j < replacementNodes.length; j++) {
+       			var insertNodes = this._createNode(uiDocument, replacementNodes[j]);
+	  			for(var k = 0; k < insertNodes.length; k++) {
+	      			nodesArray.push(insertNodes[k]);
+	      		}
+			}
+       		xap.xml.xmodify.CommandDirective.insertElement(currentNode, nodesArray, isInsertBefore);
+       		
+        } else { // some other type of node
+    		this._log.debug("Can't do insert before for this type of node"); 
+   			continue; 
         }
-
-        // Do the simple thing, at this point:
-	if (this._log.isDebug())
-		this._log.debug("Pre insert-after: <" + currentNode.nodeName+"/>:\n" + this.formatDocument(parent));
         
-        this._insertCommandArgumentsAfter(parent,currentNode) ;
-
-	if (this._log.isDebug())
-		this._log.debug("Post insert-after:  <" + currentNode.nodeName+"/>:\n" + this.formatDocument(parent) );
+	} // end for(...)
 
+}; // end _handleInsertBefore(...)
 
-        //this.insertCommandArgumentsAt(index, parent, contextNode, i);
-    }
-
-}
-
-/**
- * A helper method for the <code>insert-before</code>  directive: 
- * @param parent
- * @param contextNode
- * @throws xap.xml.xmodify.XmodifyException
- */
-xap.xml.xmodify.CommandDirective.prototype._insertCommandArgumentsAfter 
-    = function(parent,oldChild){
-    var arrArguments = this._commandArguments ;
-        for (var ii=0; ii<arrArguments.length; ++ii ) {
-        // unresolved argument: (arbitrary xml | String | CloneDirective |
-        // ValueOfDirective)*
-        var newChild = arrArguments[ii] ;
-        // Just try it for XNode and descendants so far:
-        if (oldChild instanceof google.XNode){
-            var nextOldChild = oldChild.nextSibling ;
-            if (true||nextOldChild != null){
-                parent.insertBefore(
-                            newChild.deepClone(), 
-                            nextOldChild
-                                );
-            } else {
-                // If there is no next sibling before which to insert,
-                // we can just append it to the end of the child list:
-                parent.appendChild(newChild.deepClone());                
-            }
-        } else if (this._bHtmlDocument){
-            var nextOldChild = oldChild.nextSibling ;
-            if (true||nextOldChild != null){
-                parent.insertBefore(
-                             this.makeNodeHTML(newChild), 
-                             nextOldChild
-                             );
-            } else {
-                // If there is no next sibling before which to insert,
-                // we can just append it to the end of the child list:
-                parent.appendChild(this.makeNodeHTML(newChild));                
-            }
-        } else {
-            throw new xap.xml.xmodify.XmodifyException("Can't insert the desired element before the indicated element, that target is not an XNode (or subclass tree) instance.") ;
-        }   
-    }
-}
 
 /**
- * A helper method for the <code>insert-before</code>  directive: 
- * @param parent
- * @param contextNode
+ * The insert-at command inserts its arguments (specified as children of the command element)
+ * at the specified index in the children list of each of the results returned by the XPath query.
+ * To specify the index, the command element has an attribute 'index' whose value is an integer.
+ * The valid range for the index attribute is: ( 0 - children count of the Element returned
+ * by the XPath query) inclusive on both ends. If the index is outside of this range or not an integer
+ * xap.xml.xmodify.XmodifyException exception is thrown.
+ * The XPath query must return the following set: ( Element | Document )*.
+ * If any of the results of the XPath query is not an Element or a Document, an xap.xml.xmodify.XmodifyException
+ * is thrown and the execution of the <xu:modifications/> block is halted. Note that if the XPath
+ * query selects the Document object, additional restrictions apply: the index has to be 0 and the
+ * directive element must have only 1 child Element (which will be set as the root Element of the
+ * selected Document). If these restrictions are violated, an UpdateException is thrown. 
+ * @param uiDocument		Target document
+ * @param targetNodes		Target nodes
+ * @param isInsertBefore	Toggles between insertBefore and insertAfter
  * @throws xap.xml.xmodify.XmodifyException
  */
-xap.xml.xmodify.CommandDirective.prototype._insertCommandArgumentsBefore
-    = function(parent,oldChild){
-    var arrArguments = this._commandArguments ;
-        for (var ii=0; ii<arrArguments.length; ++ii ) {
-        // unresolved argument: (arbitrary xml | String | CloneDirective |
-        // ValueOfDirective)*
-        var newChild = arrArguments[ii] ;
-        // Just try it for XNode and descendants so far:
-        if (oldChild instanceof google.XNode){
-            parent.insertBefore(
-                            newChild.deepClone(), 
-                            oldChild
-                                );
-        } else if (this._bHtmlDocument){
-            parent.insertBefore(
-                             this.makeNodeHTML(newChild), 
-                             oldChild
-                             );
-        } else {
-            throw new xap.xml.xmodify.XmodifyException("Can't insert the desired element before the indicated element, that target is not an XNode (or subclass tree) instance.") ;
-        }   
-    }
-}
-
-
+xap.xml.xmodify.CommandDirective.prototype._handleInsertAt = function(uiDocument, targetNodes)
+{
+	// check index
+	var index = parseInt(this._indexAttr, 10);
+	if((!index) || (typeof(index) != 'number')) { 
+		throw new xap.xml.xmodify.XmodifyException('Expected "index" attribute with integer value'); 
+	}
+	
+	// check if target is a document node
+	if(targetNodes.length === 0 && targetNodes[0].nodeType == google.DOM_DOCUMENT_NODE) {
+		if(this._commandArguments.length !== 0) {
+			throw new xap.xml.xmodify.XmodifyException(
+						xap.xml.xmodify.XmodifyException.SET_ROOT_ELEMENT_EXPECTS_ONE_ARG);
+		}
+		// set command argument as a new root
+		targetNodes[0].setRootElement(this._commandArguments[0]);
+		return;
+	}
+	
+	// insert into regular nodes
+	var nodes = [];
+	
+	for(var n = 0; n < targetNodes.length; n++) {
+		var childNode = targetNodes[n].childNodes[index];
+		if(!childNode) {
+			throw new xap.xml.xmodify.XmodifyException('Index out of range'); 
+		}
+		if(childNode.nodeType != google.DOM_ELEMENT_NODE) {
+			throw new xap.xml.xmodify.XmodifyException(
+				xap.xml.xmodify.XmodifyException.INVALID_NODE_FOR_COMMAND, childNode.nodeType, "insert-at");
+		}
+		nodes.push(childNode);
+	}
+	
+	// forward to insert-before
+	this._handleInsert(uiDocument, nodes, true);
+	
+}; // end _handleInsertAt(...)
 
 
-	
 /**
- * A helper method for the <code>replace</code>  directive;
- * implemented here as a (transactionally-wrappered) <code>insert-before</code>
- * the element to replace, followed by its <code>remove</code>:
- * 
- * @param contextNode
+ * A method that replaces target nodes with the new nodes.
+ * Impelemnted as remove, followed by insertBefore a nextSibling.
+ * That allows us to replace elements with the same id.
+ * We use _createNode(replacementNodes[n]) to allow <xm:clone> and <xm:value-of> constructs.
+ *   
+ * @param uiDocument
+ * @param targetNodes
  * @throws xap.xml.xmodify.XmodifyException
  */
-xap.xml.xmodify.CommandDirective.prototype._handleReplace = function(contextNode){
-
- 	/* @TODO: Validity checks */
-    var targetNodes = this._commandTargets ;  
+xap.xml.xmodify.CommandDirective.prototype._handleReplace = function(uiDocument, targetNodes) {
 
-  	if (!targetNodes.length)
-    {
-        /* Throw an exception? Alert? */
-    } 	
-
-	xap.xml.xmodify.CommandDirective.s_log.debug("Pre replacement:\n" + this.formatDocument(contextNode));
-
-    for (var ii=0; ii<targetNodes.length; ++ii ) {
-		// unresolved argument: (arbitrary xml | String | CloneDirective |
-		// ValueOfDirective)*
-		var oldChild = targetNodes[ii] ;
-		// Just try it for XNode and descendants so far:
-		if (oldChild instanceof google.XNode || this._bHtmlDocument){
-			xap.xml.xmodify.CommandDirective.s_log.debug("Pre replacing <" + oldChild.nodeName+"/>:\n" + this.formatDocument(oldChild.parentNode));
-			this._replaceWithCommandArguments(oldChild) ;
-			xap.xml.xmodify.CommandDirective.s_log.debug("Post replacing:  <" + oldChild.nodeName+"/>:\n" + this.formatDocument(oldChild.parentNode) );	
-		} else {
-			throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANNOT_REPLACE__ORIGINAL_INVALID,""+oldChild) ;
-		}	
+	if ( (!targetNodes.length) || (targetNodes.length === 0) ){
+       throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_TARGETS, "replace");
     }
-    if (this._log.isDebug())
-		this._log.debug("Post replacement:\n" + this.formatDocument(contextNode));
-    	
-}
 
+	var replacementNodes = this._commandArguments;
+	var nodesArray = [];
 
-/**
- * A helper method for the <code>insert-before</code>  directive: 
- * @param parent
- * @param contextNode
- * @throws xap.xml.xmodify.XmodifyException
- */
-xap.xml.xmodify.CommandDirective.prototype._replaceWithCommandArguments  =  function(oldChild){
-    //xap.xml.xmodify.Xmodify.DEBUG=true;
-    // Do the simple thing, at this point:
-    var parent = oldChild.parentNode ;       
-    var arrArguments = this._commandArguments ;
-    var newChild=null ;
-    try {
-     for (var ii=0; ii<arrArguments.length; ++ii ) {
-         // unresolved argument: (arbitrary xml | String | CloneDirective |
-         // ValueOfDirective)
-         newChild = arrArguments[ii] ;
-         // Just try it for XNode and descendants so far:
-         if (oldChild instanceof google.XNode){
-		if (this._log.isDebug())
-		  this._log.debug(
-		    "Pre insertion of " + this.formatDocument(newChild)+"\nbefore\n" 
-		    + this.formatDocument(oldChild)
-		    + this.formatDocument(parent) 
-                                ) ;
-          try {
-              parent.insertBefore(
-                         newChild.deepClone(), 
-                         oldChild
-                         );
-          } catch (insertionException){
-              throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANNOT_REPLACE__INSERTION,newChild.nodeName,""+insertionException);
-          }
-		if (this._log.isDebug())
-			this._log.debug(
-		    "Post insertion of " + this.formatDocument(newChild) +"\nbefore\n" 
-		    + this.formatDocument(oldChild)
-		    + this.formatDocument(parent) 
-                                ) ;                             
-         } else if (this._bHtmlDocument){
-		if (this._log.isDebug())
-		      this._log.debug(
-			"Pre insertion of " + this.formatDocument(newChild)+"\nbefore\n" 
-			+ this.formatDocument(oldChild)
-			+ this.formatDocument(parent) 
-                                    ) ;
-              try {
-                  parent.insertBefore(
-                             this.makeNodeHTML(newChild), 
-                             oldChild
-                             );
-                             
-                 // alert("parent.insertBefore(after");
-              } catch (insertionException){
-                  throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANNOT_REPLACE__INSERTION,newChild.nodeName,""+insertionException);
-              }
-              xap.xml.xmodify.CommandDirective.s_log.debug(
-                "Post insertion of " + this.formatDocument(newChild) +"\nbefore\n" 
-                + this.formatDocument(oldChild)
-                + this.formatDocument(parent) 
-                                    );                             
-         } else {
-            throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANNOT_REPLACE,oldChild.nodeName,newChild.nodeName,"unknown cause");     
-         }     
-     } // end of the iteration over all replacement nodes
-     try {
-         // all the new nodes have been inserted, so now take out the old node:
-         parent.removeChild(oldChild) ;
-     } catch (removalException){
-         // Better if we could attempt to back off all the 
-         // changes, but not yet:
-         throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANNOT_REPLACE__REMOVAL,oldChild.nodeName,""+removalException);          
-     }
-
-    } catch(replacementException){
-     throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANNOT_REPLACE,
-                       oldChild.nodeName,
-                       newChild.nodeName,
-                       ""+replacementException
-                       );     
-    } finally {
-	if (this._log.isDebug())
-		this._log.debug(
-			"Post all insertions and removals composited into replacement:"
-			+ '\n'+ this.formatDocument(parent)) ;
-    	//xap.xml.xmodify.Xmodify.DEBUG=false;
-    }// end of 'try'/catch  blocks around iteration over nodes to to replace in
-        
-} // end of _replaceWithCommandArguments()
+    for(var i = 0; i < targetNodes.length; i++ ) {
+    
+		var oldNode = targetNodes[i];
+
+		// check if defined
+		if( (!oldNode) ) { return; }
+		
+		var parentNode = oldNode.parentNode;
+
+		// check if we replace the root element
+		if( (!parentNode) ) {
+			if(replacementNodes.length != 1 || targetNodes.length != 1 || i !== 0) {
+				throw new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.SET_ROOT_ELEMENT_EXPECTS_ONE_ARG);
+			} else {
+				uiDocument.setRootElement(replacementNodes[0]);
+				return;
+			}
+		}
+		
+		// do replacement
+		for(var j = 0; j < replacementNodes.length; j++) {
+      		var insertNodes = this._createNode(uiDocument, replacementNodes[j]);
+  			for(var k = 0; k < insertNodes.length; k++) {
+      			nodesArray.push(insertNodes[k]);
+      		}
+		}
+		xap.xml.xmodify.CommandDirective.replaceElement(oldNode, nodesArray);
+		
+    } // end end for(var i = 0; i < targetNodes.length; i++ )
 
+}; // end _handleReplace()
 
 
 /**
  * Handles cloning declaration directive
- * @throw
+  *   
+ * @param uiDocument
+ * @param targetNodes
+ * @throw xap.xml.xmodify.XmodifyException.INVALID_NODE_FOR_COMMAND
  */
-xap.xml.xmodify.CommandDirective.prototype._handleClone = function(uiDocumentNode){
+xap.xml.xmodify.CommandDirective.prototype._handleClone = function(uiDocument, targetNodes)
+{
 
-    this._clones = new Array(this._commandTargets.length) ;
+    var clones = [];
 
-    for (var ll=0; ll<this._commandTargets.length; ++ll) {
-        var toClone = this._commandTargets[ll] ;
+    for(var n = 0; n < targetNodes.length; n++) {
+        var toClone = targetNodes[n] ;
         if (toClone.nodeType == google.DOM_ELEMENT_NODE) {
-            var cloned = toClone.deepClone() ;
-            this._clones[ll] = clone ;
+        	var clone = null;
+            if(toClone instanceof google.Xnode) {
+            	clone = toClone.deepClone();
+            } else { // assume HTML document
+            	clone = this.makeHtmlNode(toClone);
+            }
+            clones[n] = clone;
         } else {
             throw new xap.xml.xmodify.XmodifyException(
-                    xap.xml.xmodify.XmodifyException.CANT_BLANK_TO_NODE_TYPE, 
-                    "Clone", 
+                    xap.xml.xmodify.XmodifyException.INVALID_NODE_FOR_COMMAND, 
+                    "clone", 
                     currentNode.nodeType);
-
         }
     }
-}
+    
+    return clones;
+    
+};
 
 /**
  * Called to embed the xal components into the html document.
+ * @param uiDocument
+ * @param targetNodes
  */
-xap.xml.xmodify.CommandDirective.prototype._handleEmbedXal = function(node){		
-	var myRequires = "xap.bridges.basic.HtmlHostBridge";
-	Xap.require(myRequires);
-    var targetNodes = this._commandTargets;
+xap.xml.xmodify.CommandDirective.prototype._handleEmbedXal = function(uiDocument, targetNodes)
+{		
+	Xap.require("xap.bridges.basic.HtmlHostBridge");
     var elemsToAppend = this._commandArguments;      
-    var uiDocument =  this._session.getDocumentContainer().getUiDocument();
 
-    for (var i=0; i<targetNodes.length; i++) {
+    for(var i = 0; i < targetNodes.length; i++) {
        	var parentElement = targetNodes[i] ;
 
         //create the element and add it to the document
@@ -999,76 +827,157 @@
     	//now actually setup the html host.  	
     	htmlHostBridge.createHost(parentElement, "dojo");
     	
-    	for (var ii=0; ii<elemsToAppend.length;ii++){
-    	    hostElement.appendChild(elemsToAppend[ii]);
+    	for(var j = 0; j < elemsToAppend.length; j++){
+    	    hostElement.appendChild(elemsToAppend[j]);
     	}
 	}	
-}
+};
 
 /**
- *	Called when a set-innerhtml xModify tag is found need to add the contents of the child
+ * Called when a set-innerhtml xModify tag is found need to add the contents of the child
  * for the current node to the innerHTML of the context node.
+ * @param uiDocument
+ * @param targetNodes
  */
-xap.xml.xmodify.CommandDirective.prototype._handleSetInnerHtml = function(node){		
-    var targetNodes = this._commandTargets;
-    var elemsToAppend = this._commandArguments;      
-    var uiDocument =  this._session.getDocumentContainer().getUiDocument();
-
-    for (var i=0; i<targetNodes.length; i++) {
-       	var parentElement = targetNodes[i] ;
-    	
-    	for (var ii=0; ii<elemsToAppend.length;ii++){
-			if( elemsToAppend[ii].nodeType == google.DOM_TEXT_NODE && elemsToAppend[ii].nodeValue) {
-    	    	parentElement.innerHTML = elemsToAppend[ii].nodeValue;
+xap.xml.xmodify.CommandDirective.prototype._handleSetInnerHtml = function(uiDocument, targetNodes) 
+{		
+    var elemsToAppend = this._commandArguments;
+         
+    for(var i = 0; i < targetNodes.length; i++) {
+       	var parentElement = targetNodes[i];
+    	for(var j = 0; j < elemsToAppend.length; j++){
+			if( elemsToAppend[j].nodeType == google.DOM_TEXT_NODE && elemsToAppend[j].nodeValue) {
+    	    	parentElement.innerHTML = elemsToAppend[j].nodeValue;
     	    }
     	}
 	}	
-}
+};
+
+//-----------------------------------------------------------------------
+//
+//		Helper functions
+//
+//-----------------------------------------------------------------------
 
 /**
- * Format the supplied document into a pretty printed output string
- * Used in debug statements only.
- * @param document 
- * @return Formattes string 
+ * Creates target node(s) from the source element
+ * 
+ * @param sourceElement 	Argument to append/replace command
+ * @param isXapDocument	Is target document is XAP docuemnt or HTML document
+ * @return Target node(s)
+ */
+xap.xml.xmodify.CommandDirective.prototype._createNode = function(uiDocument, sourceElement) {
+
+	var isXapDocument = (uiDocument instanceof xap.xml.dom.Document);
+
+	// could potentially return more than one node
+	var sourceNodes = null, resultNodes = [];
+	
+	// check if this is a <xm:value-of> element
+	if(sourceElement.nodeName == 'value-of') {
+		var name = sourceElement.getAttribute('name');
+		var myVar = this._directiveSet.variables[name];
+		if(!myVar) {
+			throw new xap.xml.xmodify.XmodifyException('Unknown variable : ' + name);
+		}
+		
+		if(myVar.needClone === true) {
+			sourceNodes = myVar;
+			this._log.debug('Need to clone ' + sourceNodes.length + ' nodes from var ' + name);
+		} else {
+			// no need to clone, just return the variable (already an array)
+			return myVar;
+		}
+	} else {	// this is a regular node
+		sourceNodes = [sourceElement];
+	}
+	
+	// check if this is a <xm:clone> element
+	if(sourceElement.nodeName == 'clone') {
+		var select = sourceElement.getAttribute('select');
+		sourceNodes = xap.xml.xmodify.CommandDirective.selectMatchingNodes(uiDocument, select);
+	}
+	
+	// make nodes
+	var n = null;
+	if (isXapDocument) {
+		for(n = 0; n < sourceNodes.length; n++) {
+			resultNodes.push(sourceNodes[n].deepClone());
+		}
+	} else { //  HTML document
+		for(n = 0; n < sourceNodes.length; n++) {
+			resultNodes.push(this.makeHtmlNode(sourceNodes[n])); 
+		}
+	} // end if(isXapDocument)/else
+	
+	this._log.debug('Created ' + resultNodes.length + ' nodes ');
+	return resultNodes;
+
+}; // end _createNode
+
+
+
+
+/**
+ * Name: getType
+ * Desc: This is an accessor method for the _type protperty
+ * @return - int type of directive
  */
-xap.xml.xmodify.CommandDirective.prototype.formatDocument = function(inputDocument){
-    try{
-        //try to format catch exception.
-        return inputDocument;//.toXml(true);
-    }catch(genericException){
-        return inputDocument;
-    }
-}
+xap.xml.xmodify.CommandDirective.prototype.getType = function() { return (this._type); };
 
-/*
- * TODO - Look for possible better place to stick this.
+
+
+/**
+ * Format the supplied document into a pretty printed output string (Used in debug statements only)
+ * @param element 
+ * @return Formatted String 
  */
-xap.xml.xmodify.CommandDirective.prototype.makeNodeHTML = function(node){
-    //create the element
-    var htmlNode = document.createElement(node.getLocalName());
+xap.xml.xmodify.CommandDirective.prototype.formatDocument = function(element) {
+	return '<' + element.nodeName +  '>';
+};
+
+
+/*
+ * Creates new HTML node out of source node.
+ * @param sourceNode {Xnode} 
+ * @return HTML node with the same name and attributes as sourceNode
+ */
+xap.xml.xmodify.CommandDirective.prototype.makeHtmlNode = function(sourceNode) {
+
+	// check if text node
+	if( (sourceNode.nodeType == google.DOM_TEXT_NODE) ) {
+		if(sourceNode.nodeValue) { 
+			return (document.createTextNode(sourceNode.nodeValue)); 
+		}
+		return document.createTextNode();
+	}
+	
+
+	//create the element
+    var targetNode = document.createElement(sourceNode.nodeName);
     
     //copy over the attributes
-	for( var i=0; i<node.attributes.length; i++ ) {
-	    var key = node.attributes[i].nodeName;
-	    var value = node.attributes[i].nodeValue;
-        htmlNode.setAttribute(key, value);
+	for(var i = 0; i < sourceNode.attributes.length; i++ ) {
+	    var key = sourceNode.attributes[i].nodeName;
+	    var value = sourceNode.attributes[i].nodeValue;
+        targetNode.setAttribute(key, value);
     }
     
-    //clone the children.
-	for ( var i = 0; i < node.childNodes.length; i++ ) {
-		var child = node.childNodes[i];
-		if( child.nodeType == google.DOM_TEXT_NODE && child.nodeValue) {
-			htmlNode.appendChild(document.createTextNode(child.nodeValue));
+    //clone the children
+	for(var j = 0; j < sourceNode.childNodes.length; j++ ) {
+		var childNode = sourceNode.childNodes[j];
+		if( (childNode.nodeType == google.DOM_TEXT_NODE) ) {
+			if(childNode.nodeValue) { targetNode.appendChild(document.createTextNode(childNode.nodeValue)); }
 		}else{
-		    htmlNode.appendChild(this.makeNodeHTML(child));
+		    targetNode.appendChild(this.makeHtmlNode(childNode));
 		}
 	}
     
     //return the new html node
-    return htmlNode;
-}
+    return targetNode;
+};
 
 
 //End of xap.xml.xmodify.CommandDirective
 
-    
\ No newline at end of file
+    

Modified: incubator/xap/trunk/codebase/src/xap/xml/xmodify/DirectiveSet.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/xml/xmodify/DirectiveSet.js?view=diff&rev=510832&r1=510831&r2=510832
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/xml/xmodify/DirectiveSet.js (original)
+++ incubator/xap/trunk/codebase/src/xap/xml/xmodify/DirectiveSet.js Thu Feb 22 21:10:45 2007
@@ -18,40 +18,66 @@
  */
  
 Xap.provide('xap.xml.xmodify.DirectiveSet'); 
-
 Xap.require("xap.xml.xmodify.CommandDirective");
 
- 
+/**
+ *	@fileoverview Creates a DirectiveSet instance and
+ *  an instance of CommandDirective for each modifiation directive in set.
+ *
+**/
+
+//----------------------------------------------------------------------
+// Constructors.
+//----------------------------------------------------------------------
+
+/**
+ *	Creates an instance of Object with DirectiveSet function.
+ *
+ *	@param modificationsElement <xm:modifications> element
+ *	@param session {xap.session.ClientSession} Current Session object.
+**/
 xap.xml.xmodify.DirectiveSet = function( modificationsElement, session){
-	this._directives  = this._createDirectives(modificationsElement.childNodes, session);
-}
+	this._directives = this._createDirectives(modificationsElement.childNodes, session);
+}; // end Constructor
+
 
+/**
+*	Name: execute
+*	Desc: Executes each CommandDirective agains the current document
+*
+*	@param uiDocument {Document} The DOM document.
+*	@param baseUrl {String} The base URL
+*
+*/
 xap.xml.xmodify.DirectiveSet.prototype.execute = function(uiDocument, baseUrl)
 {
-   for (var i = 0;
-        i < this._directives.length;
-        i++)
-    {	// Seems to want the root element here:
-           this._directives[i].execute(uiDocument, baseUrl);
-    }
-
-}
-
-xap.xml.xmodify.DirectiveSet.prototype._createDirectives = function(elemsDirectives, session)
+   for (var i = 0;  i < this._directives.length; i++) {	
+		this._directives[i].execute(uiDocument, baseUrl);
+   }
+
+}; // end execute()
+
+
+/**
+*	Name: 	_createDirectives
+*	Desc: 	Creates a set of CommandDirective objects
+*			from the set of child nodes of modifications element.
+*
+*	@param elements {Element []} Xmodify directives like <append>, <replace>, etc.
+*	@param session {xap.session.ClientSession} Current Session object.
+*/
+xap.xml.xmodify.DirectiveSet.prototype._createDirectives = function(elements, session)
 {
-   var dirs = new Array();
-
-   for (var i = 0;
-        i < elemsDirectives.length;
-        i++)
-       {
-          dirs[dirs.length] = new xap.xml.xmodify.CommandDirective (elemsDirectives[i], session);
-
-       } /* end for i */
+   var directives = [];
 
-    return(dirs);
+   for (var i = 0; i < elements.length; i++) {
+   		var commandDirective = new xap.xml.xmodify.CommandDirective(elements[i], session, this);
+		directives.push(commandDirective);
+   }
+    
+   return (directives);
 
-} /* end _createDirectives */
+}; /* end _createDirectives */
 
 
 

Modified: incubator/xap/trunk/codebase/src/xap/xml/xmodify/UpdateDirective.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/xml/xmodify/UpdateDirective.js?view=diff&rev=510832&r1=510831&r2=510832
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/xml/xmodify/UpdateDirective.js (original)
+++ incubator/xap/trunk/codebase/src/xap/xml/xmodify/UpdateDirective.js Thu Feb 22 21:10:45 2007
@@ -21,33 +21,25 @@
 Xap.require("xap.xml.xmodify.XmodifyException");
 
 /**
- * Base class for XMLUpdate xap.xml.xmodify.CommandDirective.
+ * The list of directive names for xap.xml.xmodify.CommandDirective.
  * 
  * @version modeled after Java $Revision: 1.6 $
- * @author Johnny@hisown.com
- */
+ * @author johnny@hisown.com
+  */
 
 
-/**
- * Constructor 
- * 
- * @param elemDirectiveElement - element representing the directive
- */
-xap.xml.xmodify.UpdateDirective = function(elemDirectiveElement)
-{
+//----------------------------------------------------------------------
+// Constructors.
+//----------------------------------------------------------------------
 
-  /* Change a command directive into a directive object */
 
-   /* Javascript doesnt have trim, so we make our own */
+xap.xml.xmodify.UpdateDirective = function() { }; // end UpdateDirective()
 
-  this._strType = elemDirectiveElement.getLocalName( ) ;
-  this._type = xap.xml.xmodify.UpdateDirective.getDirectiveTypeAsInt(this._strType);
-  this._directiveElement = elemDirectiveElement;
-}
 
 //----------------------------------------------------------------------
 // Constants
 //----------------------------------------------------------------------
+
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_VARIABLE = 0;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_ATTRIBUTE = 1;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_VALUE_OF = 2;
@@ -55,26 +47,24 @@
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_INSERT_BEFORE = 4;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_APPEND = 5;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_SET_ATTRIBUTE = 6;
-xap.xml.xmodify.UpdateDirective.DIRECTIVE_REPLACE = 7
+xap.xml.xmodify.UpdateDirective.DIRECTIVE_REPLACE = 7;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_REPLACE_CHILDREN = 8;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_ELEMENT = 9;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_ATTRIBUTE = 10;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_INSERT_AT = 11;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_CLONE = 12;
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_CREATE_DOCUMENT = 13;
-xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_CHILD = 14;
-xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_CHILDREN = 15;
 
 /**
  * Used only by HTML documents.
  */
-xap.xml.xmodify.UpdateDirective.DIRECTIVE_EMBED_XAL = 16;
-xap.xml.xmodify.UpdateDirective.DIRECTIVE_SET_INNER_HTML = 17;
+xap.xml.xmodify.UpdateDirective.DIRECTIVE_EMBED_XAL = 14;
+xap.xml.xmodify.UpdateDirective.DIRECTIVE_SET_INNER_HTML = 15;
 
 /**
  * Used to do integer/string translation:
 **/
-xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES = new Array(0);
+xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES = [];
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_VARIABLE]      =  "variable" ;        
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_ATTRIBUTE]     =  "attribute" ;       
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_VALUE_OF]      =  "value-of" ;        
@@ -89,8 +79,6 @@
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_INSERT_AT]         =  "insert-at" ;       
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_CLONE]             =  "clone" ;       
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_CREATE_DOCUMENT]   =  "create-document" ; 
-xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_CHILD]      =  "remove-child" ;    
-xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_REMOVE_CHILDREN]   =  "remove-children" ; 
 
 /**
  * Used only by HTML documents.
@@ -98,50 +86,28 @@
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_EMBED_XAL]   =  "embed-xal" ; 
 xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[xap.xml.xmodify.UpdateDirective.DIRECTIVE_SET_INNER_HTML]   =  "set-innerhtml" ; 
 
-//--------------------------------------------------------------------
-//  Package Protected Class Methods.
-//--------------------------------------------------------------------
+
+//-----------------------------------------------------------------------
+// Public Methods. (publc instance methods)
+//-----------------------------------------------------------------------
+
+
 /**
- * Convenience method for converting directive types
+ * Helper function to define directives
  * 
- * @param directive - string representation of the directive type
+ * @param directiveName - directive name (tag name)
  * @return - int representation of the directive type
  */
-xap.xml.xmodify.UpdateDirective.getDirectiveTypeAsInt = function (strDirective)
-{
-   for (i = 0 ; i < xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES.length ; i++)
-     {
-         if (xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[i] == strDirective)
-           {
-               return (i);
-           }
-     } /* end for */
+xap.xml.xmodify.UpdateDirective.getType = function(directiveName) {
 
-  throw (xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.UNKNOWN_COMMAND, strDirective));
+	for(var i = 0; i < xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES.length; i++)  {
+	    if (xap.xml.xmodify.UpdateDirective.DIRECTIVE_NAMES[i] == directiveName) {  
+	    	return (i);
+	    }
+	}
+	throw (new xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.UNKNOWN_COMMAND, directiveName));
+	
+}; // end getType(directiveName)
 
-} /* end getDirectiveTypeAsInt */
 
-//----------------------------------------------------------------------
-// Constructors.
-//----------------------------------------------------------------------
-
-
-
-//----------------------------------------------------------------------
-// Public instance methods
-//----------------------------------------------------------------------
-
-/**
- *  Accessor method for the _type protperty
- * @return - int type of directive
- */
-xap.xml.xmodify.UpdateDirective.prototype.getType = function()
-{
-   return(this._type);
-}
-
-xap.xml.xmodify.UpdateDirective.prototype.getDirectiveElement = function()
-{
-    return(this._directiveElement);
-}
 

Modified: incubator/xap/trunk/codebase/src/xap/xml/xmodify/Xmodify.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/xml/xmodify/Xmodify.js?view=diff&rev=510832&r1=510831&r2=510832
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/xml/xmodify/Xmodify.js (original)
+++ incubator/xap/trunk/codebase/src/xap/xml/xmodify/Xmodify.js Thu Feb 22 21:10:45 2007
@@ -18,33 +18,58 @@
  */
 
 Xap.provide( "xap.xml.xmodify.Xmodify" ) ;
-
-
 Xap.require( "xap.xml.xmodify.DirectiveSet" ) ;
  
 /**
+ * @fileoverview Creates an object instance with Xmodify and 
+ * initializes a directiveSet instance.
+ *
  * @author xap@hisown.com
+ * @author mmikhaylov
  */
-xap.xml.xmodify.Xmodify = function( modificationsElement, session)
+ 
+
+//-----------------------------------------------------------------------
+// Constructors.
+//-----------------------------------------------------------------------
+
+/**
+ *
+ * @param modificationsElement <xm:modifications> node
+ * @param session current session object
+**/
+xap.xml.xmodify.Xmodify = function( modificationsElement, session )
 {
    this._modificationsElement = modificationsElement;
    this._session = session;
    this._directiveSet = new xap.xml.xmodify.DirectiveSet(modificationsElement, session);
-   var checkThisOutOnDebugging = true ; 
-}
+};
+
+
+//-----------------------------------------------------------------------
+// Class Methods
+//-----------------------------------------------------------------------
+
+// empty
 
 //-----------------------------------------------------------------------
 // Public Methods. (publc instance methods)
 //-----------------------------------------------------------------------
 
+/**
+ *
+ *	Executes the set of modification directives.
+ *
+**/
 xap.xml.xmodify.Xmodify.prototype.execute = function (){
+
     /*
      * Execute our commandsDoc on the UIDocument from the container 
      */
     var executionDocument = this._modificationsElement.getAttribute("document");
     var uiDoc = null;
 
-    if (executionDocument == null || executionDocument == "ui"){
+    if (executionDocument === null || executionDocument == "ui"){
        uiDoc = this._session.getDocumentContainer().getUiDocument();
     }else if (executionDocument == "html"){
        uiDoc = document;
@@ -54,7 +79,8 @@
 	 * Start the machinery put into place on creation:
 	 */
     this._directiveSet.execute(uiDoc, this._modificationsElement.baseUrl);
-}  /* end execute */
+		
+};  /* end execute */
 
 //-----------------------------------------------------------------------
 // Private Methods. (private Instance) 

Modified: incubator/xap/trunk/codebase/src/xap/xml/xmodify/XmodifyException.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/codebase/src/xap/xml/xmodify/XmodifyException.js?view=diff&rev=510832&r1=510831&r2=510832
==============================================================================
--- incubator/xap/trunk/codebase/src/xap/xml/xmodify/XmodifyException.js (original)
+++ incubator/xap/trunk/codebase/src/xap/xml/xmodify/XmodifyException.js Thu Feb 22 21:10:45 2007
@@ -16,58 +16,66 @@
  *  limitations under the License.
  *
  */
+ 
+ 
+ /**
+ *
+ *	@fileoverview Throwable exception object.
+ *
+ **/
 
 Xap.provide('xap.xml.xmodify.XmodifyException'); 
 
- //TODO this entire class needs revamp, for the time being we will leave it as is
- 
- /**
+/**
   * xap.xml.xmodify.XmodifyException is the port of UpdateException
   *
   * Notice how we use this is
-  *
   * throw(xap.xml.xmodify.XmodifyException(xap.xml.xmodify.XmodifyException.CANT_BLANK_TO_NODE_TYPE , "append", "Text"));
   *
-  *
-  * @author JL@HisOwn.com
   */
-
-xap.xml.xmodify.XmodifyException = function(){
-	var message = arguments[0] ;
-	for( var ii=1; ii<arguments.length; ++ii){
-		message = message.replace("%s", arguments[ii]) ;
+xap.xml.xmodify.XmodifyException = function() {
+	var message = arguments[0];
+	for( var i = 1; i < arguments.length; i++) {
+		message = message.replace("%s", arguments[i]) ;
 	}
 	this._message = message;
-}
+};
 
+/**
+*	Override for toString() function.
+*
+*/
 xap.xml.xmodify.XmodifyException.prototype.toString = function(){
 	return this._message;
-}
+};
 
 //-----------------------------------------------------------------------
 // Constants. (public static final)
 //-----------------------------------------------------------------------
 
-xap.xml.xmodify.XmodifyException.CANT_BLANK_TO_NODE_TYPE = "Can't %s to %s";
-xap.xml.xmodify.XmodifyException.SET_ROOT_ELEMENT_EXPECTS_ONE_ARG = "setRootElement() Expects one arg";
-xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_ONE_ARG = "%s Expects one arg";
-xap.xml.xmodify.XmodifyException.ATTRIBUTE_ARGUMENT_NOT_ATTRIB_DIRECTIVE = "Attribute argument %s is not an attribute directive!";
+
+xap.xml.xmodify.XmodifyException.SET_ROOT_ELEMENT_EXPECTS_ONE_ARG = "setRootElement() expects one argument";
+
+xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_TARGETS	= "Command %s expects target node(s)";
+xap.xml.xmodify.XmodifyException.COMMAND_EXPECTS_ONE_ARG	= "Command %s expects exactly one argument";
+xap.xml.xmodify.XmodifyException.INVALID_NODE_FOR_COMMAND	= "Invalid node %s for command %s";
+
+
+xap.xml.xmodify.XmodifyException.ATTRIBUTE_ARGUMENT_NOT_ATTRIB_DIRECTIVE = "Attribute argument (%s) is not an attribute directive!";
+
 xap.xml.xmodify.XmodifyException.UNKNOWN_COMMAND = "Directive %s is unrecognized";
 xap.xml.xmodify.XmodifyException.INVALID_INSERT_AFTER_BECAUSE_OF_PARENT = "The XPath statement resolved to type %s which does not have a parent. Therefore an insert after cannot be performed." ;
 xap.xml.xmodify.XmodifyException.INVALID_INSERT_BEFORE_BECAUSE_OF_PARENT = "The XPath statement resolved to type %s which does not have a parent. Therefore an insert before cannot be performed." ;
 xap.xml.xmodify.XmodifyException.CHILDREN_CANT_BE_ADDED = "The XPath statement returned a node to which children may not be added: %s" ;
+
+
 // We're at first doing replacement as a composition of insert-before and remove:
 xap.xml.xmodify.XmodifyException.CANNOT_REPLACE = "Some problem replacing node <%s/> with node <%s/>:  %s" ;
 xap.xml.xmodify.XmodifyException.CANNOT_REPLACE__REMOVAL = "Some problem removing old node <%s/>: %s" ;
 xap.xml.xmodify.XmodifyException.CANNOT_REPLACE__INSERTION = "Some problem inserting new node <%s/>: %s" ;
-xap.xml.xmodify.XmodifyException.CANNOT_REPLACE__ORIGINAL_INVALID
-="Can't replace the selected element with the indicated element, "
-  +"the selected element was null or otherwise not an XNode instance: %s."
-  
+xap.xml.xmodify.XmodifyException.CANNOT_REPLACE__ORIGINAL_INVALID = "Can't replace the selected element with the indicated element, the selected element was null or otherwise not an XNode instance: %s.";
 xap.xml.xmodify.XmodifyException.ZERO_RESULTS = "The XPath statement %s returned 0 results." ;
 xap.xml.xmodify.XmodifyException.UNSPECIFIED_EXCEPTION ="Unspecified xap.xml.xmodify.Xmodify exception." ;
-
-
 
 
 



Mime
View raw message