domDiff.js
/**
 * Given existing nodes list and modified node list, the function will attempt to correlate nodes across the lists to determine an action to be taken against each. Actions are 
 * CREATE, UPDATE or DELETE.
 * relatedXpathsToCompare - In some cases there are other XML elements that are not within the node but are related to it. This list represents relative paths for the each node in existNodeList, modNodeList
 * criticalNodeNames - A string array containing node element names that are critical to the comparison. If there is a difference containing ANY of them, then it is the nodes are considered different regardless of other element similarity
 * Actions:
 * If nodes have the same criticalNodeNames, then the action will be UPDATE
 * If nodes are in the modNodeList do not have overlap in criticalNodeNames nodes, then CREATE
 * If nodes in the existNodeList remain after the two above elimination steps, then they are considered existing nodes that no longer are in the new list and therefore DELETE
 * @return  Object containing create nodes, update nodes and delete nodes. Each list reflects the action that needs to be conducted on said nodes
 */
Given existing nodes list and modified node list, the function will attempt to correlate nodes across the lists to determine an action to be taken against each. Actions are
CREATE, UPDATE or DELETE.
relatedXpathsToCompare - In some cases there are other XML elements that are not within the node but are related to it. This list represents relative paths for the each node in existNodeList, modNodeList
criticalNodeNames - A string array containing node element names that are critical to the comparison. If there is a difference containing ANY of them, then it is the nodes are considered different regardless of other element similarity
Actions:
If nodes have the same criticalNodeNames, then the action will be UPDATE
If nodes are in the modNodeList do not have overlap in criticalNodeNames nodes, then CREATE
If nodes in the existNodeList remain after the two above elimination steps, then they are considered existing nodes that no longer are in the new list and therefore DELETE
@return  Object containing create nodes, update nodes and delete nodes. Each list reflects the action that needs to be conducted on said nodes
Given existing nodes list and modified node list the function will attempt to correlate nodes across the lists to determine an action to be taken against each . Actions are CREATE UPDATE or DELETE . relatedXpathsToCompare - In some cases there are other XML elements that are not within the node but are related to it . This list represents relative paths for the each node in existNodeList modNodeList criticalNodeNames - A string array containing node element names that are critical to the comparison . If there is a difference containing ANY of them then it is the nodes are considered different regardless of other element similarity Actions : If nodes have the same criticalNodeNames then the action will be UPDATE If nodes are in the modNodeList do not have overlap in criticalNodeNames nodes then CREATE If nodes in the existNodeList remain after the two above elimination steps then they are considered existing nodes that no longer are in the new list and therefore DELETE @return Object containing create nodes update nodes and delete nodes . Each list reflects the action that needs to be conducted on said nodes
function determineNodesAction(existNodeList, modNodeList, relatedXpathsToCompare, criticalNodeNames)
{
	let createNodes = [];
	let updateNodes = [];
	let deleteNodes = [];
	for(let i = modNodeList.length-1; i >= 0; i--) 
	{
		let modNodeCommitedToAction = false;
		for(let j = existNodeList.length-1; j >= 0; j--)
		{
			log.debug({message: `existNodes index ${j}/${existNodeList.length}, modNodes index ${i}/${modNodeList.length}`});
			let diffDegree = calcNodeAggregateDifference(existNodeList[j], modNodeList[i], relatedXpathsToCompare, criticalNodeNames);
			if(diffDegree.diffIsInCriticalNodes == false)
			{ 
				updateNodes.push(modNodeList[i]); 
				existNodeList.splice(j, 1); 
				modNodeList.splice(i, 1);
				log.debug({message: `U - Flagged node for UPDATE action`});
				modNodeCommitedToAction = true;
				break; 
			}
		}
		if(modNodeCommitedToAction == false)
		{ 
			createNodes.push(modNodeList[i]);
			modNodeList.splice(i, 1);
			log.debug({message: `C - Flagged node for CREATE action`});
		}
	}
	if(modNodeList.length > 0)
	{
		log.error({message: `DANGER: The modified node list still has nodes left in it. This should not happen and there is a logic error in the application. modNodeList content: ${JSON.stringify(modNodeList)}`});
	}
	if(existNodeList.length > 0)
	{
		for(let i = 0; i < existNodeList.length; i++)
		{
			deleteNodes.push(existNodeList[i]);
		}
		log.debug({message: `R - Flagged ${deleteNodes.length} node(s) for DELETE action`});
	}
	log.info({message: `Action Summary: ${createNodes.length} flagged for CREATE, ${updateNodes.length} flagged for UPDATE, ${deleteNodes.length} flagged for DELETE`});
	let nodeActions = {};
	if(!underscore.isEmpty(createNodes))
	{
		nodeActions[ACTION_TYPE.CREATE] = createNodes;
	}
	if(!underscore.isEmpty(updateNodes))
	{
		nodeActions[ACTION_TYPE.UPDATE] = updateNodes;
	}
	if(!underscore.isEmpty(deleteNodes))
	{
		nodeActions[ACTION_TYPE.DELETE] = deleteNodes;
	}
	return nodeActions;
}
function determineNodesAction ( existNodeList , modNodeList , relatedXpathsToCompare , criticalNodeNames ) { let createNodes = [ ] ; let updateNodes = [ ] ; let deleteNodes = [ ] ; for ( let i = modNodeList . length - 1 ; i >= 0 ; i -- ) { let modNodeCommitedToAction = false ; for ( let j = existNodeList . length - 1 ; j >= 0 ; j -- ) { log . debug ( { message : ` ${ j } ${ existNodeList . length } ${ i } ${ modNodeList . length } ` } ) ; let diffDegree = calcNodeAggregateDifference ( existNodeList [ j ] , modNodeList [ i ] , relatedXpathsToCompare , criticalNodeNames ) ; if ( diffDegree . diffIsInCriticalNodes == false ) { updateNodes . push ( modNodeList [ i ] ) ; existNodeList . splice ( j , 1 ) ; modNodeList . splice ( i , 1 ) ; log . debug ( { message : ` ` } ) ; modNodeCommitedToAction = true ; break ; } } if ( modNodeCommitedToAction == false ) { createNodes . push ( modNodeList [ i ] ) ; modNodeList . splice ( i , 1 ) ; log . debug ( { message : ` ` } ) ; } } if ( modNodeList . length > 0 ) { log . error ( { message : ` ${ JSON . stringify ( modNodeList ) } ` } ) ; } if ( existNodeList . length > 0 ) { for ( let i = 0 ; i < existNodeList . length ; i ++ ) { deleteNodes . push ( existNodeList [ i ] ) ; } log . debug ( { message : ` ${ deleteNodes . length } ` } ) ; } log . info ( { message : ` ${ createNodes . length } ${ updateNodes . length } ${ deleteNodes . length } ` } ) ; let nodeActions = { } ; if ( ! underscore . isEmpty ( createNodes ) ) { nodeActions [ ACTION_TYPE . CREATE ] = createNodes ; } if ( ! underscore . isEmpty ( updateNodes ) ) { nodeActions [ ACTION_TYPE . UPDATE ] = updateNodes ; } if ( ! underscore . isEmpty ( deleteNodes ) ) { nodeActions [ ACTION_TYPE . DELETE ] = deleteNodes ; } return nodeActions ; }
Given existing nodes list and modified node list, the function will attempt to correlate nodes across the lists to determine an action to be taken against each.
Given existing nodes list and modified node list the function will attempt to correlate nodes across the lists to determine an action to be taken against each .
//starting from the end of the list because code below will remove entries from array //let diffDegree = calcNodeDifference(existNodeList[j], modNodeList[i], criticalNodeNames); //there is a difference, but it is not in the critical fields, this is an update case //this is the modified node that needs to be used //delete this entry since it has a match //the object from the outerloop has already been commited to an action, no need to continue in inner loop //there was not a node similar to this one in the existing nodes list, therefore it must be a new node //at this point the modNodeList should be empty, but the existNodeList could have some items left, which will become delete candidates