Browse Source

Rework of the ModelFactory API to make it simpler and safer.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@3347 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 10 years ago
parent
commit
ce00241d3d
2 changed files with 53 additions and 47 deletions
  1. 2 2
      setup/compiler.class.inc.php
  2. 51 45
      setup/modelfactory.class.inc.php

+ 2 - 2
setup/compiler.class.inc.php

@@ -106,7 +106,7 @@ class MFCompiler
 		//
 		//
 		$aMenuNodes = array();
 		$aMenuNodes = array();
 		$aMenusByModule = array();
 		$aMenusByModule = array();
-		foreach ($this->oFactory->ListActiveChildNodes('menus', 'menu') as $oMenuNode)
+		foreach ($this->oFactory->GetNodes('menus/menu') as $oMenuNode)
 		{
 		{
 			$sMenuId = $oMenuNode->getAttribute('id');
 			$sMenuId = $oMenuNode->getAttribute('id');
 			$aMenuNodes[$sMenuId] = $oMenuNode;
 			$aMenuNodes[$sMenuId] = $oMenuNode;
@@ -320,7 +320,7 @@ EOF;
 			mkdir($sDictDir, 0777, true);
 			mkdir($sDictDir, 0777, true);
 		}
 		}
 
 
-		$oDictionaries = $this->oFactory->ListActiveChildNodes('dictionaries', 'dictionary');
+		$oDictionaries = $this->oFactory->GetNodes('dictionaries/dictionary');
 		foreach($oDictionaries as $oDictionaryNode)
 		foreach($oDictionaries as $oDictionaryNode)
 		{
 		{
 			$this->CompileDictionary($oDictionaryNode, $sTempTargetDir, $sFinalTargetDir);
 			$this->CompileDictionary($oDictionaryNode, $sTempTargetDir, $sFinalTargetDir);

+ 51 - 45
setup/modelfactory.class.inc.php

@@ -262,7 +262,7 @@ class ModelFactory
 	 * To progressively replace LoadModule
 	 * To progressively replace LoadModule
 	 * @param xxx xxx
 	 * @param xxx xxx
 	 */
 	 */
-	public function LoadDelta(DOMDocument $oDeltaDoc, $oSourceNode, $oTargetParentNode)
+	public function LoadDelta($oSourceNode, $oTargetParentNode)
 	{
 	{
 		if (!$oSourceNode instanceof DOMElement) return;
 		if (!$oSourceNode instanceof DOMElement) return;
 		//echo "Load $oSourceNode->tagName::".$oSourceNode->getAttribute('id')." (".$oSourceNode->getAttribute('_delta').")<br/>\n";
 		//echo "Load $oSourceNode->tagName::".$oSourceNode->getAttribute('id')." (".$oSourceNode->getAttribute('_delta').")<br/>\n";
@@ -312,13 +312,13 @@ class ModelFactory
 			foreach($oSourceNode->childNodes as $oSourceChild)
 			foreach($oSourceNode->childNodes as $oSourceChild)
 			{
 			{
 				// Continue deeper
 				// Continue deeper
-				$this->LoadDelta($oDeltaDoc, $oSourceChild, $oTargetNode);
+				$this->LoadDelta($oSourceChild, $oTargetNode);
 			}			
 			}			
 			break;
 			break;
 
 
 		case 'define_if_not_exists':
 		case 'define_if_not_exists':
-			$oExistingNode = $oTargetParentNode->FindExistingChildNode($oSourceNode);
-			if ($oExistingNode == null)
+			$oExistingNode = $oTargetParentNode->_FindChildNode($oSourceNode);
+			if ( ($oExistingNode == null) || ($oExistingNode->getAttribute('_alteration') == 'removed') )
 			{
 			{
 				// Same as 'define' below
 				// Same as 'define' below
 				$oTargetNode = $oTarget->ImportNode($oSourceNode, true);
 				$oTargetNode = $oTarget->ImportNode($oSourceNode, true);
@@ -345,8 +345,8 @@ class ModelFactory
 			break;
 			break;
 
 
 		case 'delete':
 		case 'delete':
-			$oTargetNode = $oTargetParentNode->FindExistingChildNode($oSourceNode);
-			if($oTargetNode == null)
+			$oTargetNode = $oTargetParentNode->_FindChildNode($oSourceNode);
+			if ( ($oTargetNode == null) || ($oTargetNode->getAttribute('_alteration') == 'removed') )
 			{
 			{
 				throw new Exception("Trying to delete node for {$oSourceNode->tagName} (id:".$oSourceNode->getAttribute('id').") under {$oTargetParentNode->tagName} (id:".$oTargetParentNode->getAttribute('id').'). but nothing found.');
 				throw new Exception("Trying to delete node for {$oSourceNode->tagName} (id:".$oSourceNode->getAttribute('id').") under {$oTargetParentNode->tagName} (id:".$oTargetParentNode->getAttribute('id').'). but nothing found.');
 			}
 			}
@@ -453,8 +453,18 @@ class ModelFactory
 					}
 					}
 				}
 				}
 				
 				
+				// Adjust the XML to transparently add an id (=value) on all values of an enum which don't already have one.
+				// This enables altering an enum for just adding/removing one value, intead of redefining the whole list of values.
+				$oNodeList = $oXPath->query("/itop_design/classes//class/fields/field[@xsi:type='AttributeEnum']/values/value");
+				foreach($oNodeList as $oNode)
+				{
+					if ($oNode->getAttribute('id') == '')
+					{
+						$oNode->SetAttribute('id', $oNode->textContent);
+					}
+				}				
 				$oDeltaRoot = $oDocument->childNodes->item(0);
 				$oDeltaRoot = $oDocument->childNodes->item(0);
-				$this->LoadDelta($oDocument, $oDeltaRoot, $this->oDOMDocument);
+				$this->LoadDelta($oDeltaRoot, $this->oDOMDocument);
 			}
 			}
 			
 			
 			$aDictionaries = $oModule->GetDictionaryFiles();
 			$aDictionaries = $oModule->GetDictionaryFiles();
@@ -1224,7 +1234,7 @@ EOF
 	
 	
 	public function ListChanges()
 	public function ListChanges()
 	{
 	{
-		return $this->GetNodes('//*[@_alteration or @_old_id]');
+		return $this->oDOMDocument->GetNodes('//*[@_alteration or @_old_id]', null, false /* not safe */);
 	}
 	}
 
 
 
 
@@ -1464,7 +1474,7 @@ EOF;
 			//$oDeltaDoc->Dump();
 			//$oDeltaDoc->Dump();
 			//$this->oDOMDocument->Dump();
 			//$this->oDOMDocument->Dump();
 			$oDeltaRoot = $oDeltaDoc->childNodes->item(0);
 			$oDeltaRoot = $oDeltaDoc->childNodes->item(0);
-			$this->LoadDelta($oDeltaDoc, $oDeltaRoot, $this->oDOMDocument);
+			$this->LoadDelta($oDeltaRoot, $this->oDOMDocument);
 			//$oRoot->Dump();
 			//$oRoot->Dump();
 			$sDOMRebuilt = $oRoot->Dump(true);
 			$sDOMRebuilt = $oRoot->Dump(true);
 		}
 		}
@@ -1515,12 +1525,6 @@ EOF;
 	{
 	{
 		return $this->oDOMDocument->GetNodes($sXPath, $oContextNode);
 		return $this->oDOMDocument->GetNodes($sXPath, $oContextNode);
 	}
 	}
-
-	public function ListActiveChildNodes($sContextXPath, $sTagName)
-	{
-		$oContextPath = $this->oRoot->GetNodes($sContextXPath)->item(0);
-		return $oContextPath->ListActiveChildNodes($sTagName);
-	}
 }
 }
 
 
 
 
@@ -1547,7 +1551,7 @@ class MFElement extends DOMElement
 	{
 	{
 		return $this->ownerDocument->GetNodes($sXPath, $this);
 		return $this->ownerDocument->GetNodes($sXPath, $this);
 	}
 	}
-
+	
 	/**
 	/**
 	 * Extracts some nodes from the DOM (active nodes only !!!)
 	 * Extracts some nodes from the DOM (active nodes only !!!)
 	 * @param string $sXPath A XPath expression
 	 * @param string $sXPath A XPath expression
@@ -1588,7 +1592,7 @@ class MFElement extends DOMElement
 		$oNode = null;
 		$oNode = null;
 		foreach($this->childNodes as $oChildNode)
 		foreach($this->childNodes as $oChildNode)
 		{
 		{
-			if ($oChildNode->nodeName == $sTagName)
+			if (($oChildNode->nodeName == $sTagName) && (($oChildNode->getAttribute('_alteration') != 'removed')))
 			{
 			{
 				$oNode = $oChildNode;
 				$oNode = $oChildNode;
 				break;
 				break;
@@ -1742,7 +1746,7 @@ class MFElement extends DOMElement
 	/**
 	/**
 	 * Helper to remove child nodes	
 	 * Helper to remove child nodes	
 	 */	
 	 */	
-	public function DeleteChildren()
+	protected function DeleteChildren()
 	{
 	{
 		while (isset($this->firstChild))
 		while (isset($this->firstChild))
 		{
 		{
@@ -1755,23 +1759,26 @@ class MFElement extends DOMElement
 	} 
 	} 
 
 
 	/**
 	/**
-	 * Find the child node matching the given node
+	 * Find the child node matching the given node.
+	 * UNSAFE: may return nodes marked as _alteration="removed"
+	 * A method with the same signature MUST exist in MFDocument for the recursion to work fine
 	 * @param MFElement $oRefNode The node to search for
 	 * @param MFElement $oRefNode The node to search for
-	 * @param bool      $sSearchId substitutes to the value of the 'id' attribute 
+	 * @param string    $sSearchId substitutes to the value of the 'id' attribute 
 	 */	
 	 */	
-	public function FindExistingChildNode(MFElement $oRefNode, $sSearchId = null)
+	public function _FindChildNode(MFElement $oRefNode, $sSearchId = null)
 	{
 	{
-		return self::FindNode($this, $oRefNode, $sSearchId);
+		return self::_FindNode($this, $oRefNode, $sSearchId);
 	}
 	}
 	
 	
 	/**
 	/**
-	 * Seems to work fine (and is about 10 times faster than above) EXCEPT for menus !!!!
-	 * @param unknown_type $oParent
-	 * @param unknown_type $oRefNode
-	 * @param unknown_type $sSearchId
+	 * Find the child node matching the given node under the specified parent.
+	 * UNSAFE: may return nodes marked as _alteration="removed"
+	 * @param DOMNode $oParent
+	 * @param MFElement $oRefNode
+	 * @param string $sSearchId
 	 * @throws Exception
 	 * @throws Exception
 	 */
 	 */
-	public static function FindNode(DOMNode $oParent, MFElement $oRefNode, $sSearchId = null)
+	public static function _FindNode(DOMNode $oParent, MFElement $oRefNode, $sSearchId = null)
 	{
 	{
 		$oRes = null;
 		$oRes = null;
 		if ($oParent instanceof DOMDocument)
 		if ($oParent instanceof DOMDocument)
@@ -1806,13 +1813,6 @@ class MFElement extends DOMElement
 		}
 		}
 		return $oRes;
 		return $oRes;
 	}
 	}
-	
-	public function ListActiveChildNodes($sTagName)
-	{
-		$sXPath = $sTagName."[not(@_alteration) or @_alteration!='removed']";
-		return $this->GetNodes($sXPath);
-	}
-
 
 
 	/**
 	/**
 	 * Check if the current node is under a node 'added' or 'altered'
 	 * Check if the current node is under a node 'added' or 'altered'
@@ -1841,7 +1841,7 @@ class MFElement extends DOMElement
 		// First: cleanup any flag behind the new node
 		// First: cleanup any flag behind the new node
 		$oNode->ApplyChanges();
 		$oNode->ApplyChanges();
 	
 	
-		$oExisting = $this->FindExistingChildNode($oNode);
+		$oExisting = $this->_FindChildNode($oNode);
 		if ($oExisting)
 		if ($oExisting)
 		{
 		{
 			if ($oExisting->getAttribute('_alteration') != 'removed')
 			if ($oExisting->getAttribute('_alteration') != 'removed')
@@ -1871,7 +1871,7 @@ class MFElement extends DOMElement
 		// First: cleanup any flag behind the new node
 		// First: cleanup any flag behind the new node
 		$oNode->ApplyChanges();
 		$oNode->ApplyChanges();
 
 
-		$oExisting = $this->FindExistingChildNode($oNode, $sSearchId);
+		$oExisting = $this->_FindChildNode($oNode, $sSearchId);
 		if (!$oExisting)
 		if (!$oExisting)
 		{
 		{
 			throw new Exception("Attempting to modify a non existing node: $oNode->tagName (id: ".$oNode->getAttribute('id').")");
 			throw new Exception("Attempting to modify a non existing node: $oNode->tagName (id: ".$oNode->getAttribute('id').")");
@@ -1902,7 +1902,7 @@ class MFElement extends DOMElement
 		// First: cleanup any flag behind the new node
 		// First: cleanup any flag behind the new node
 		$oNode->ApplyChanges();
 		$oNode->ApplyChanges();
 
 
-		$oExisting = $this->FindExistingChildNode($oNode, $sSearchId);
+		$oExisting = $this->_FindChildNode($oNode, $sSearchId);
 		if ($oExisting)
 		if ($oExisting)
 		{
 		{
 			$sPrevFlag = $oExisting->getAttribute('_alteration');
 			$sPrevFlag = $oExisting->getAttribute('_alteration');
@@ -2016,7 +2016,7 @@ class MFElement extends DOMElement
 	 */
 	 */
 	public function MergeInto($oContainer, $sSearchId, $bMustExist)
 	public function MergeInto($oContainer, $sSearchId, $bMustExist)
 	{
 	{
-		$oTargetNode = $oContainer->FindExistingChildNode($this, $sSearchId);
+		$oTargetNode = $oContainer->_FindChildNode($this, $sSearchId);
 		if ($oTargetNode)
 		if ($oTargetNode)
 		{
 		{
 			if ($oTargetNode->getAttribute('_alteration') == 'removed')
 			if ($oTargetNode->getAttribute('_alteration') == 'removed')
@@ -2111,7 +2111,7 @@ class MFElement extends DOMElement
 	public function ListChanges()
 	public function ListChanges()
 	{
 	{
 		// Note: omitting the dot will make the query be global to the whole document!!!
 		// Note: omitting the dot will make the query be global to the whole document!!!
-		return $this->GetNodes('.//*[@_alteration or @_old_id]');
+		return $this->ownerDocument->GetNodes('.//*[@_alteration or @_old_id]', $this, false);
 	}
 	}
 
 
 	/**
 	/**
@@ -2218,12 +2218,13 @@ class MFDocument extends DOMDocument
 
 
 	/**
 	/**
 	 * Find the child node matching the given node
 	 * Find the child node matching the given node
+	 * A method with the same signature MUST exist in MFElement for the recursion to work fine
 	 * @param MFElement $oRefNode The node to search for
 	 * @param MFElement $oRefNode The node to search for
-	 * @param bool      $sSearchId substitutes to the value of the 'id' attribute 
+	 * @param string    $sSearchId substitutes to the value of the 'id' attribute 
 	 */	
 	 */	
-	public function FindExistingChildNode(MFElement $oRefNode, $sSearchId = null)
+	public function _FindChildNode(MFElement $oRefNode, $sSearchId = null)
 	{
 	{
-		return MFElement::FindNode($this, $oRefNode, $sSearchId);
+		return MFElement::_FindNode($this, $oRefNode, $sSearchId);
 	}
 	}
 
 
 	/**
 	/**
@@ -2231,18 +2232,23 @@ class MFDocument extends DOMDocument
 	 * @param string $sXPath A XPath expression
 	 * @param string $sXPath A XPath expression
 	 * @return DOMNodeList
 	 * @return DOMNodeList
 	 */
 	 */
-	public function GetNodes($sXPath, $oContextNode = null)
+	public function GetNodes($sXPath, $oContextNode = null, $bSafe = true)
 	{
 	{
 		$oXPath = new DOMXPath($this);
 		$oXPath = new DOMXPath($this);
+		if ($bSafe)
+		{
+			$sXPath .= "[not(@_alteration) or @_alteration!='removed']";
+		}
 		
 		
 		if (is_null($oContextNode))
 		if (is_null($oContextNode))
 		{
 		{
-			return $oXPath->query($sXPath);
+			$oResult = $oXPath->query($sXPath);
 		}
 		}
 		else
 		else
 		{
 		{
-			return $oXPath->query($sXPath, $oContextNode);
+			$oResult = $oXPath->query($sXPath, $oContextNode);
 		}
 		}
+		return $oResult;
 	}
 	}
 	
 	
 	public function GetNodeById($sXPath, $sId, $oContextNode = null)
 	public function GetNodeById($sXPath, $sId, $oContextNode = null)