Переглянути джерело

Compiler: reviewed the xml format to facilitate generalization of operations (e.g. compute a delta)

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1955 a333f486-631f-4898-b8df-5754b55c2be0
romainq 13 роки тому
батько
коміт
341cad1e34

+ 22 - 22
core/attributedef.class.inc.php

@@ -133,7 +133,7 @@ abstract class AttributeDefinition
 
 	// Note: I could factorize this code with the parameter management made for the AttributeDef class
 	// to be overloaded
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array();
 	}
@@ -447,7 +447,7 @@ abstract class AttributeDefinition
  */
 class AttributeLinkedSet extends AttributeDefinition
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("allowed_values", "depends_on", "linked_class", "ext_key_to_me", "count_min", "count_max"));
 	}
@@ -757,7 +757,7 @@ class AttributeLinkedSet extends AttributeDefinition
  */
 class AttributeLinkedSetIndirect extends AttributeLinkedSet
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("ext_key_to_remote"));
 	}
@@ -774,7 +774,7 @@ class AttributeLinkedSetIndirect extends AttributeLinkedSet
  */
 class AttributeDBFieldVoid extends AttributeDefinition
 {	
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("allowed_values", "depends_on", "sql"));
 	}
@@ -860,7 +860,7 @@ class AttributeDBFieldVoid extends AttributeDefinition
  */
 class AttributeDBField extends AttributeDBFieldVoid
 {	
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("default_value", "is_null_allowed"));
 	}
@@ -875,7 +875,7 @@ class AttributeDBField extends AttributeDBFieldVoid
  */
 class AttributeInteger extends AttributeDBField
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return parent::ListExpectedParams();
 		//return array_merge(parent::ListExpectedParams(), array());
@@ -1007,7 +1007,7 @@ class AttributePercentage extends AttributeInteger
  */
 class AttributeDecimal extends AttributeDBField
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array('digits', 'decimals' /* including precision */));
 	}
@@ -1102,7 +1102,7 @@ class AttributeDecimal extends AttributeDBField
  */
 class AttributeBoolean extends AttributeInteger
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return parent::ListExpectedParams();
 		//return array_merge(parent::ListExpectedParams(), array());
@@ -1133,7 +1133,7 @@ class AttributeBoolean extends AttributeInteger
  */
 class AttributeString extends AttributeDBField
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return parent::ListExpectedParams();
 		//return array_merge(parent::ListExpectedParams(), array());
@@ -1259,7 +1259,7 @@ class AttributeString extends AttributeDBField
  */
 class AttributeClass extends AttributeString
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("class_category", "more_values"));
 	}
@@ -1311,7 +1311,7 @@ class AttributeClass extends AttributeString
  */
 class AttributeApplicationLanguage extends AttributeString
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return parent::ListExpectedParams();
 	}
@@ -1401,7 +1401,7 @@ class AttributeFinalClass extends AttributeString
  */
 class AttributePassword extends AttributeString
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return parent::ListExpectedParams();
 		//return array_merge(parent::ListExpectedParams(), array());
@@ -1969,7 +1969,7 @@ class AttributeTemplateHTML extends AttributeText
  */
 class AttributeEnum extends AttributeString
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return parent::ListExpectedParams();
 		//return array_merge(parent::ListExpectedParams(), array());
@@ -2146,7 +2146,7 @@ class AttributeDateTime extends AttributeDBField
 		return "Y-m-d H:i:s";
 	}
 
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return parent::ListExpectedParams();
 		//return array_merge(parent::ListExpectedParams(), array());
@@ -2457,7 +2457,7 @@ class AttributeDate extends AttributeDateTime
 		return "Y-m-d";
 	}
 
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return parent::ListExpectedParams();
 		//return array_merge(parent::ListExpectedParams(), array());
@@ -2543,7 +2543,7 @@ class AttributeDeadline extends AttributeDateTime
  */
 class AttributeExternalKey extends AttributeDBFieldVoid
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("targetclass", "is_null_allowed", "on_target_delete"));
 	}
@@ -2660,7 +2660,7 @@ class AttributeHierarchicalKey extends AttributeExternalKey
 {
 	protected $m_sTargetClass;
 
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		$aParams = parent::ListExpectedParams();
 		$idx = array_search('targetclass', $aParams);
@@ -2784,7 +2784,7 @@ class AttributeHierarchicalKey extends AttributeExternalKey
  */
 class AttributeExternalField extends AttributeDefinition
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("extkey_attcode", "target_attcode"));
 	}
@@ -3011,7 +3011,7 @@ class AttributeExternalField extends AttributeDefinition
  */
 class AttributeURL extends AttributeString
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		//return parent::ListExpectedParams();
 		return array_merge(parent::ListExpectedParams(), array("target"));
@@ -3045,7 +3045,7 @@ class AttributeURL extends AttributeString
  */
 class AttributeBlob extends AttributeDefinition
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("depends_on"));
 	}
@@ -3192,7 +3192,7 @@ class AttributeBlob extends AttributeDefinition
  */
 class AttributeOneWayPassword extends AttributeDefinition
 {
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array("depends_on"));
 	}
@@ -3465,7 +3465,7 @@ class AttributePropertySet extends AttributeTable
  */
 class AttributeComputedFieldVoid extends AttributeDefinition
 {	
-	static protected function ListExpectedParams()
+	static public function ListExpectedParams()
 	{
 		return array_merge(parent::ListExpectedParams(), array());
 	}

+ 1 - 1
core/metamodel.class.php

@@ -1341,7 +1341,7 @@ abstract class MetaModel
 						$sRemoteAttCode = $oAttDef->GetExtAttCode()."_friendlyname";
 						$sFriendlyNameAttCode = $sAttCode.'_friendlyname';
 						// propagate "is_null_allowed" ? 
-						$oFriendlyName = new AttributeExternalField($sFriendlyNameAttCode, array("allowed_values"=>null, "extkey_attcode"=>$sKeyAttCode, "target_attcode"=>$sRemoteAttCode, "is_null_allowed"=>true, "depends_on"=>array()));
+						$oFriendlyName = new AttributeExternalField($sFriendlyNameAttCode, array("allowed_values"=>null, "extkey_attcode"=>$sKeyAttCode, "target_attcode"=>$sRemoteAttCode, "depends_on"=>array()));
 						$oFriendlyName->SetHostClass($sClass);
 						self::$m_aAttribDefs[$sClass][$sFriendlyNameAttCode] = $oFriendlyName;
 						self::$m_aAttribOrigins[$sClass][$sFriendlyNameAttCode] = $sRemoteClass;

+ 66 - 20
datamodel/itop-attachments/datamodel.itop-attachments.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <classes>
-    <class name="Attachment" category="addon,bizmodel" parent="DBObject" abstract="false" key_type="autoincrement" db_table="attachment" db_key_field="id" db_final_class_field="">
+    <class id="Attachment">
       <properties>
         <comment><![CDATA[/**
  * Module attachments
@@ -16,34 +16,67 @@
  * @author      Denis Flaven <denis.flaven@combodo.com>
  * @license     http://www.opensource.org/licenses/gpl-3.0.html LGPL
  */]]></comment>
-        <naming format="%1$s %2$s">
+        <category>addon,bizmodel</category>
+        <parent>DBObject</parent>
+        <abstract>false</abstract>
+        <key_type>autoincrement</key_type>
+        <db_table>attachment</db_table>
+        <db_key_field>id</db_key_field>
+        <db_final_class_field></db_final_class_field>
+        <naming>
+          <format>%1$s %2$s</format>
           <attributes>
-            <attribute name="item_class"/>
-            <attribute name="temp_id"/>
+            <attribute id="item_class"/>
+            <attribute id="temp_id"/>
           </attributes>
         </naming>
         <display_template></display_template>
         <icon></icon>
         <reconciliation>
           <attributes>
-            <attribute name=""/>
+            <attribute id=""/>
           </attributes>
         </reconciliation>
       </properties>
       <fields>
-        <field name="expire" xsi:type="AttributeDateTime" sql="expire" default_value="" is_null_allowed="false"/>
-        <field name="temp_id" xsi:type="AttributeString" sql="temp_id" default_value="" is_null_allowed="true"/>
-        <field name="item_class" xsi:type="AttributeString" sql="item_class" default_value="" is_null_allowed="false"/>
-        <field name="item_id" xsi:type="AttributeString" sql="item_id" default_value="" is_null_allowed="true"/>
-        <field name="item_org_id" xsi:type="AttributeInteger" sql="item_org_id" default_value="0" is_null_allowed="true"/>
-        <field name="contents" xsi:type="AttributeBlob"/>
+        <field id="expire" xsi:type="AttributeDateTime">
+          <sql>expire</sql>
+          <default_value></default_value>
+          <is_null_allowed>false</is_null_allowed>
+        </field>
+        <field id="temp_id" xsi:type="AttributeString">
+          <sql>temp_id</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="item_class" xsi:type="AttributeString">
+          <sql>item_class</sql>
+          <default_value></default_value>
+          <is_null_allowed>false</is_null_allowed>
+        </field>
+        <field id="item_id" xsi:type="AttributeString">
+          <sql>item_id</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="item_org_id" xsi:type="AttributeInteger">
+          <sql>item_org_id</sql>
+          <default_value>0</default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="contents" xsi:type="AttributeBlob"/>
       </fields>
       <methods>
-        <method name="MapContextParam" static="true" access="public" type="Overload-ExNihilo"><comment><![CDATA[/**
+        <method id="MapContextParam">
+          <comment><![CDATA[/**
 	 * Maps the given context parameter name to the appropriate filter/search code for this class
 	 * @param string $sContextParam Name of the context parameter, e.g. 'org_id'
 	 * @return string Filter code, e.g. 'customer_id'
-	 */]]></comment><![CDATA[	public static function MapContextParam($sContextParam)
+	 */]]></comment>
+          <static>true</static>
+          <access>public</access>
+          <type>Overload-ExNihilo</type>
+          <code><![CDATA[	public static function MapContextParam($sContextParam)
 	{
 		if ($sContextParam == 'org_id')
 		{
@@ -53,12 +86,18 @@
 		{
 			return null;
 		}
-	}]]></method>
-        <method name="SetItem" static="false" access="public" type="Overload-ExNihilo"><comment><![CDATA[/**
+	}]]></code>
+        </method>
+        <method id="SetItem">
+          <comment><![CDATA[/**
 	 * Set/Update all of the '_item' fields
 	 * @param object $oItem Container item
 	 * @return void
-	 */]]></comment><![CDATA[	public function SetItem($oItem, $bUpdateOnChange = false)
+	 */]]></comment>
+          <static>false</static>
+          <access>public</access>
+          <type>Overload-ExNihilo</type>
+          <code><![CDATA[	public function SetItem($oItem, $bUpdateOnChange = false)
 	{
 		$sClass = get_class($oItem);
 		$iItemId = $oItem->GetKey();
@@ -86,11 +125,17 @@
 				}
 			}
 		}
-	}]]></method>
-        <method name="SetDefaultOrgId" static="false" access="public" type="Overload-ExNihilo"><comment><![CDATA[/**
+	}]]></code>
+        </method>
+        <method id="SetDefaultOrgId">
+          <comment>/**
 	 * Give a default value for item_org_id (if relevant...)
 	 * @return void
-	 */]]></comment><![CDATA[	public function SetDefaultOrgId()
+	 */</comment>
+          <static>false</static>
+          <access>public</access>
+          <type>Overload-ExNihilo</type>
+          <code><![CDATA[	public function SetDefaultOrgId()
 	{
 		// First check that the organization CAN be fetched from the target class
 		//
@@ -123,7 +168,8 @@
 				}
 			}
 		}
-	}]]></method>
+	}]]></code>
+        </method>
       </methods>
       <presentation>
         <details>

Різницю між файлами не показано, бо вона завелика
+ 810 - 409
datamodel/itop-change-mgmt-1.0.0/datamodel.itop-change-mgmt.xml


Різницю між файлами не показано, бо вона завелика
+ 602 - 160
datamodel/itop-config-mgmt-1.0.0/datamodel.itop-config-mgmt.xml


Різницю між файлами не показано, бо вона завелика
+ 576 - 339
datamodel/itop-incident-mgmt-1.0.0/datamodel.itop-incident-mgmt.xml


+ 203 - 61
datamodel/itop-knownerror-mgmt-1.0.0/datamodel.itop-knownerror-mgmt.xml

@@ -1,49 +1,126 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <classes>
-    <class name="KnownError" category="bizmodel,searchable,knownerrormgmt" parent="cmdbAbstractObject" abstract="false" key_type="autoincrement" db_table="known_error" db_key_field="id" db_final_class_field="">
+    <class id="KnownError">
       <properties>
-        <comment><![CDATA[/**
+        <comment>/**
 * Description of known error
-*/]]></comment>
-        <naming format="%1$s">
+*/</comment>
+        <category>bizmodel,searchable,knownerrormgmt</category>
+        <parent>cmdbAbstractObject</parent>
+        <abstract>false</abstract>
+        <key_type>autoincrement</key_type>
+        <db_table>known_error</db_table>
+        <db_key_field>id</db_key_field>
+        <db_final_class_field></db_final_class_field>
+        <naming>
+          <format>%1$s</format>
           <attributes>
-            <attribute name="name"/>
+            <attribute id="name"/>
           </attributes>
         </naming>
         <display_template></display_template>
         <icon>images/known-error.png</icon>
         <reconciliation>
           <attributes>
-            <attribute name="org_id"/>
-            <attribute name="name"/>
+            <attribute id="org_id"/>
+            <attribute id="name"/>
           </attributes>
         </reconciliation>
       </properties>
       <fields>
-        <field name="name" xsi:type="AttributeString" sql="name" default_value="" is_null_allowed="false"/>
-        <field name="org_id" xsi:type="AttributeExternalKey" target_class="Organization" jointype="" sql="cust_id" is_null_allowed="false" on_target_delete="DEL_MANUAL"/>
-        <field name="cust_name" xsi:type="AttributeExternalField" extkey_attcode="org_id" target_attcode="name"/>
-        <field name="problem_id" xsi:type="AttributeExternalKey" target_class="Problem" jointype="" sql="problem_id" is_null_allowed="true" on_target_delete="DEL_MANUAL"/>
-        <field name="problem_ref" xsi:type="AttributeExternalField" extkey_attcode="problem_id" target_attcode="ref"/>
-        <field name="symptom" xsi:type="AttributeText" sql="symptom" default_value="" is_null_allowed="false"/>
-        <field name="root_cause" xsi:type="AttributeText" sql="rootcause" default_value="" is_null_allowed="true"/>
-        <field name="workaround" xsi:type="AttributeText" sql="workaround" default_value="" is_null_allowed="true"/>
-        <field name="solution" xsi:type="AttributeText" sql="solution" default_value="" is_null_allowed="true"/>
-        <field name="error_code" xsi:type="AttributeString" sql="error_code" default_value="" is_null_allowed="true"/>
-        <field name="domain" xsi:type="AttributeEnum" sql="domain" default_value="Application" is_null_allowed="false">
+        <field id="name" xsi:type="AttributeString">
+          <sql>name</sql>
+          <default_value></default_value>
+          <is_null_allowed>false</is_null_allowed>
+        </field>
+        <field id="org_id" xsi:type="AttributeExternalKey">
+          <sql>cust_id</sql>
+          <target_class>Organization</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_MANUAL</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="cust_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>org_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
+        </field>
+        <field id="problem_id" xsi:type="AttributeExternalKey">
+          <sql>problem_id</sql>
+          <target_class>Problem</target_class>
+          <is_null_allowed>true</is_null_allowed>
+          <on_target_delete>DEL_MANUAL</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="problem_ref" xsi:type="AttributeExternalField">
+          <extkey_attcode>problem_id</extkey_attcode>
+          <target_attcode>ref</target_attcode>
+        </field>
+        <field id="symptom" xsi:type="AttributeText">
+          <sql>symptom</sql>
+          <default_value></default_value>
+          <is_null_allowed>false</is_null_allowed>
+        </field>
+        <field id="root_cause" xsi:type="AttributeText">
+          <sql>rootcause</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="workaround" xsi:type="AttributeText">
+          <sql>workaround</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="solution" xsi:type="AttributeText">
+          <sql>solution</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="error_code" xsi:type="AttributeString">
+          <sql>error_code</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="domain" xsi:type="AttributeEnum">
           <values>
             <value>Network</value>
             <value>Server</value>
             <value>Application</value>
             <value>Desktop</value>
           </values>
+          <sql>domain</sql>
+          <default_value>Application</default_value>
+          <is_null_allowed>false</is_null_allowed>
+        </field>
+        <field id="vendor" xsi:type="AttributeString">
+          <sql>vendor</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="model" xsi:type="AttributeString">
+          <sql>model</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="version" xsi:type="AttributeString">
+          <sql>version</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="ci_list" xsi:type="AttributeLinkedSetIndirect">
+          <linked_class>lnkInfraError</linked_class>
+          <ext_key_to_me>error_id</ext_key_to_me>
+          <count_min>0</count_min>
+          <count_max>0</count_max>
+          <ext_key_to_remote>infra_id</ext_key_to_remote>
+        </field>
+        <field id="document_list" xsi:type="AttributeLinkedSetIndirect">
+          <linked_class>lnkDocumentError</linked_class>
+          <ext_key_to_me>error_id</ext_key_to_me>
+          <count_min>0</count_min>
+          <count_max>0</count_max>
+          <ext_key_to_remote>doc_id</ext_key_to_remote>
         </field>
-        <field name="vendor" xsi:type="AttributeString" sql="vendor" default_value="" is_null_allowed="true"/>
-        <field name="model" xsi:type="AttributeString" sql="model" default_value="" is_null_allowed="true"/>
-        <field name="version" xsi:type="AttributeString" sql="version" default_value="" is_null_allowed="true"/>
-        <field name="ci_list" xsi:type="AttributeLinkedSetIndirect" linked_class="lnkInfraError" ext_key_to_me="error_id" ext_key_to_remote="infra_id" count_min="0" count_max="0"/>
-        <field name="document_list" xsi:type="AttributeLinkedSetIndirect" linked_class="lnkDocumentError" ext_key_to_me="error_id" ext_key_to_remote="doc_id" count_min="0" count_max="0"/>
       </fields>
       <methods/>
       <presentation>
@@ -85,30 +162,64 @@
         </list>
       </presentation>
     </class>
-    <class name="lnkInfraError" category="bizmodel,searchable,knownerrormgmt,lnkknownerror" parent="cmdbAbstractObject" abstract="false" key_type="autoincrement" is_link="1" db_table="infra_error_links" db_key_field="link_id" db_final_class_field="">
+    <class id="lnkInfraError">
       <properties>
-        <comment><![CDATA[/**
+        <comment>/**
 * n-n link between any Infra and a Known Error
-*/]]></comment>
-        <naming format="lnkInfraError">
+*/</comment>
+        <is_link>1</is_link>
+        <category>bizmodel,searchable,knownerrormgmt,lnkknownerror</category>
+        <parent>cmdbAbstractObject</parent>
+        <abstract>false</abstract>
+        <key_type>autoincrement</key_type>
+        <db_table>infra_error_links</db_table>
+        <db_key_field>link_id</db_key_field>
+        <db_final_class_field></db_final_class_field>
+        <naming>
+          <format>lnkInfraError</format>
           <attributes/>
         </naming>
         <display_template></display_template>
         <icon></icon>
         <reconciliation>
           <attributes>
-            <attribute name="infra_id"/>
-            <attribute name="error_id"/>
+            <attribute id="infra_id"/>
+            <attribute id="error_id"/>
           </attributes>
         </reconciliation>
       </properties>
       <fields>
-        <field name="infra_id" xsi:type="AttributeExternalKey" target_class="FunctionalCI" jointype="" sql="infra_id" is_null_allowed="false" on_target_delete="DEL_AUTO"/>
-        <field name="infra_name" xsi:type="AttributeExternalField" extkey_attcode="infra_id" target_attcode="name"/>
-        <field name="infra_status" xsi:type="AttributeExternalField" extkey_attcode="infra_id" target_attcode="status"/>
-        <field name="error_id" xsi:type="AttributeExternalKey" target_class="KnownError" jointype="" sql="error_id" is_null_allowed="false" on_target_delete="DEL_AUTO"/>
-        <field name="error_name" xsi:type="AttributeExternalField" extkey_attcode="error_id" target_attcode="name"/>
-        <field name="reason" xsi:type="AttributeString" sql="dummy" default_value="" is_null_allowed="true"/>
+        <field id="infra_id" xsi:type="AttributeExternalKey">
+          <sql>infra_id</sql>
+          <target_class>FunctionalCI</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_AUTO</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="infra_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>infra_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
+        </field>
+        <field id="infra_status" xsi:type="AttributeExternalField">
+          <extkey_attcode>infra_id</extkey_attcode>
+          <target_attcode>status</target_attcode>
+        </field>
+        <field id="error_id" xsi:type="AttributeExternalKey">
+          <sql>error_id</sql>
+          <target_class>KnownError</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_AUTO</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="error_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>error_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
+        </field>
+        <field id="reason" xsi:type="AttributeString">
+          <sql>dummy</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
       </fields>
       <methods/>
       <presentation>
@@ -135,31 +246,62 @@
         </list>
       </presentation>
     </class>
-    <class name="lnkDocumentError" category="bizmodel,searchable,knownerrormgmt,lnkknownerror" parent="cmdbAbstractObject" abstract="false" key_type="autoincrement" is_link="1" db_table="documents_error_link" db_key_field="link_id" db_final_class_field="">
+    <class id="lnkDocumentError">
       <properties>
-        <comment><![CDATA[/**
+        <comment>/**
 * n-n link between any Contract and a Document
-*/]]></comment>
-        <naming format="%1$s">
+*/</comment>
+        <is_link>1</is_link>
+        <category>bizmodel,searchable,knownerrormgmt,lnkknownerror</category>
+        <parent>cmdbAbstractObject</parent>
+        <abstract>false</abstract>
+        <key_type>autoincrement</key_type>
+        <db_table>documents_error_link</db_table>
+        <db_key_field>link_id</db_key_field>
+        <db_final_class_field></db_final_class_field>
+        <naming>
+          <format>%1$s</format>
           <attributes>
-            <attribute name="link_type"/>
+            <attribute id="link_type"/>
           </attributes>
         </naming>
         <display_template>../business/templates/default.html</display_template>
         <icon></icon>
         <reconciliation>
           <attributes>
-            <attribute name="doc_id"/>
-            <attribute name="error_id"/>
+            <attribute id="doc_id"/>
+            <attribute id="error_id"/>
           </attributes>
         </reconciliation>
       </properties>
       <fields>
-        <field name="doc_id" xsi:type="AttributeExternalKey" target_class="Document" jointype="" sql="doc_id" is_null_allowed="false" on_target_delete="DEL_AUTO"/>
-        <field name="doc_name" xsi:type="AttributeExternalField" extkey_attcode="doc_id" target_attcode="name"/>
-        <field name="error_id" xsi:type="AttributeExternalKey" target_class="KnownError" jointype="" sql="error_id" is_null_allowed="false" on_target_delete="DEL_AUTO"/>
-        <field name="error_name" xsi:type="AttributeExternalField" extkey_attcode="error_id" target_attcode="name"/>
-        <field name="link_type" xsi:type="AttributeString" sql="link_type" default_value="" is_null_allowed="true"/>
+        <field id="doc_id" xsi:type="AttributeExternalKey">
+          <sql>doc_id</sql>
+          <target_class>Document</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_AUTO</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="doc_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>doc_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
+        </field>
+        <field id="error_id" xsi:type="AttributeExternalKey">
+          <sql>error_id</sql>
+          <target_class>KnownError</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_AUTO</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="error_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>error_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
+        </field>
+        <field id="link_type" xsi:type="AttributeString">
+          <sql>link_type</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
       </fields>
       <methods/>
       <presentation>
@@ -182,28 +324,28 @@
   </classes>
   <menus>
     <menu id="ProblemManagement" xsi:type="MenuGroup">
-      <rank value="42"/>
+      <rank>42</rank>
     </menu>
     <menu id="NewError" xsi:type="NewObjectMenuNode">
-      <rank value="3"/>
-      <parent value="ProblemManagement"/>
-      <class value="KnownError"/>
+      <rank>3</rank>
+      <parent>ProblemManagement</parent>
+      <class>KnownError</class>
     </menu>
     <menu id="SearchError" xsi:type="SearchMenuNode">
-      <rank value="4"/>
-      <parent value="ProblemManagement"/>
-      <class value="KnownError"/>
+      <rank>4</rank>
+      <parent>ProblemManagement</parent>
+      <class>KnownError</class>
     </menu>
     <menu id="Problem:Shortcuts" xsi:type="TemplateMenuNode">
-      <rank value="5"/>
-      <parent value="ProblemManagement"/>
-      <template_file value=""/>
+      <rank>5</rank>
+      <parent>ProblemManagement</parent>
+      <template_file></template_file>
     </menu>
     <menu id="Problem:KnownErrors" xsi:type="OQLMenuNode">
-      <rank value="3"/>
-      <parent value="Problem:Shortcuts"/>
-      <oql value="SELECT KnownError"/>
-      <do_search value="1"/>
+      <rank>3</rank>
+      <parent>Problem:Shortcuts</parent>
+      <oql>SELECT KnownError</oql>
+      <do_search>1</do_search>
     </menu>
   </menus>
 </itop_design>

+ 441 - 217
datamodel/itop-problem-mgmt-1.0.0/datamodel.itop-problem-mgmt.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <classes>
-    <class name="Problem" category="bizmodel,searchable,problemmgmt" parent="Ticket" abstract="false" key_type="autoincrement" db_table="ticket_problem" db_key_field="id" db_final_class_field="">
+    <class id="Problem">
       <properties>
         <comment><![CDATA[/**
  * Persistent classes for a CMDB
@@ -11,296 +11,514 @@
  * @author      Denis Flaven <denis.flaven@combodo.com>
  * @license     http://www.opensource.org/licenses/gpl-3.0.html LGPL
  */]]></comment>
-        <naming format="%1$s">
+        <category>bizmodel,searchable,problemmgmt</category>
+        <parent>Ticket</parent>
+        <abstract>false</abstract>
+        <key_type>autoincrement</key_type>
+        <db_table>ticket_problem</db_table>
+        <db_key_field>id</db_key_field>
+        <db_final_class_field></db_final_class_field>
+        <naming>
+          <format>%1$s</format>
           <attributes>
-            <attribute name="ref"/>
+            <attribute id="ref"/>
           </attributes>
         </naming>
         <display_template></display_template>
         <icon>images/problem.png</icon>
         <reconciliation>
           <attributes>
-            <attribute name="ref"/>
+            <attribute id="ref"/>
           </attributes>
         </reconciliation>
         <order>
           <columns>
-            <column name="ref" ascending="false"/>
+            <column id="ref" order="0">
+              <ascending>false</ascending>
+            </column>
           </columns>
         </order>
       </properties>
       <fields>
-        <field name="status" xsi:type="AttributeEnum" sql="status" default_value="new" is_null_allowed="false">
+        <field id="status" xsi:type="AttributeEnum">
           <values>
             <value>new</value>
             <value>assigned</value>
             <value>resolved</value>
             <value>closed</value>
           </values>
+          <sql>status</sql>
+          <default_value>new</default_value>
+          <is_null_allowed>false</is_null_allowed>
         </field>
-        <field name="org_id" xsi:type="AttributeExternalKey" target_class="Organization" jointype="" sql="org_id" is_null_allowed="false" on_target_delete="DEL_AUTO"/>
-        <field name="org_name" xsi:type="AttributeExternalField" extkey_attcode="org_id" target_attcode="name"/>
-        <field name="service_id" xsi:type="AttributeExternalKey" target_class="Service" jointype="" filter="SELECT Service AS s JOIN SLA AS sla ON sla.service_id=s.id JOIN lnkContractToSLA AS ln ON ln.sla_id=sla.id JOIN CustomerContract AS cc ON ln.contract_id=cc.id WHERE cc.org_id =:this-&gt;org_id" sql="service_id" is_null_allowed="false" on_target_delete="DEL_MANUAL">
+        <field id="org_id" xsi:type="AttributeExternalKey">
+          <sql>org_id</sql>
+          <target_class>Organization</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_AUTO</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="org_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>org_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
+        </field>
+        <field id="service_id" xsi:type="AttributeExternalKey">
+          <filter><![CDATA[SELECT Service AS s JOIN SLA AS sla ON sla.service_id=s.id JOIN lnkContractToSLA AS ln ON ln.sla_id=sla.id JOIN CustomerContract AS cc ON ln.contract_id=cc.id WHERE cc.org_id =:this->org_id]]></filter>
           <dependencies>
-            <attribute name="org_id"/>
+            <attribute id="org_id"/>
           </dependencies>
+          <sql>service_id</sql>
+          <target_class>Service</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_MANUAL</on_target_delete>
+          <jointype></jointype>
         </field>
-        <field name="service_name" xsi:type="AttributeExternalField" extkey_attcode="service_id" target_attcode="name"/>
-        <field name="servicesubcategory_id" xsi:type="AttributeExternalKey" target_class="ServiceSubcategory" jointype="" filter="SELECT ServiceSubcategory WHERE service_id = :this-&gt;service_id" sql="servicesubcategory_id" is_null_allowed="false" on_target_delete="DEL_MANUAL">
+        <field id="service_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>service_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
+        </field>
+        <field id="servicesubcategory_id" xsi:type="AttributeExternalKey">
+          <filter><![CDATA[SELECT ServiceSubcategory WHERE service_id = :this->service_id]]></filter>
           <dependencies>
-            <attribute name="service_id"/>
+            <attribute id="service_id"/>
           </dependencies>
+          <sql>servicesubcategory_id</sql>
+          <target_class>ServiceSubcategory</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_MANUAL</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="servicesubcategory_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>servicesubcategory_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
         </field>
-        <field name="servicesubcategory_name" xsi:type="AttributeExternalField" extkey_attcode="servicesubcategory_id" target_attcode="name"/>
-        <field name="product" xsi:type="AttributeString" sql="product" default_value="" is_null_allowed="true"/>
-        <field name="impact" xsi:type="AttributeEnum" sql="impact" default_value="1" is_null_allowed="false">
+        <field id="product" xsi:type="AttributeString">
+          <sql>product</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="impact" xsi:type="AttributeEnum">
           <values>
             <value>1</value>
             <value>2</value>
             <value>3</value>
           </values>
+          <sql>impact</sql>
+          <default_value>1</default_value>
+          <is_null_allowed>false</is_null_allowed>
         </field>
-        <field name="urgency" xsi:type="AttributeEnum" sql="urgency" default_value="1" is_null_allowed="false">
+        <field id="urgency" xsi:type="AttributeEnum">
           <values>
             <value>1</value>
             <value>2</value>
             <value>3</value>
           </values>
+          <sql>urgency</sql>
+          <default_value>1</default_value>
+          <is_null_allowed>false</is_null_allowed>
         </field>
-        <field name="priority" xsi:type="AttributeEnum" sql="priority" default_value="1" is_null_allowed="false">
+        <field id="priority" xsi:type="AttributeEnum">
           <values>
             <value>1</value>
             <value>2</value>
             <value>3</value>
           </values>
+          <sql>priority</sql>
+          <default_value>1</default_value>
+          <is_null_allowed>false</is_null_allowed>
         </field>
-        <field name="workgroup_id" xsi:type="AttributeExternalKey" target_class="Team" jointype="" filter="SELECT Team AS t JOIN CustomerContract AS cc ON cc.support_team_id=t.id JOIN lnkContractToSLA AS ln ON ln.contract_id=cc.id JOIN SLA AS sla ON ln.sla_id=sla.id WHERE sla.service_id = :this-&gt;service_id AND cc.org_id = :this-&gt;org_id" sql="workgroup_id" is_null_allowed="false" on_target_delete="DEL_MANUAL">
+        <field id="workgroup_id" xsi:type="AttributeExternalKey">
+          <filter><![CDATA[SELECT Team AS t JOIN CustomerContract AS cc ON cc.support_team_id=t.id JOIN lnkContractToSLA AS ln ON ln.contract_id=cc.id JOIN SLA AS sla ON ln.sla_id=sla.id WHERE sla.service_id = :this->service_id AND cc.org_id = :this->org_id]]></filter>
           <dependencies>
-            <attribute name="org_id"/>
-            <attribute name="service_id"/>
+            <attribute id="org_id"/>
+            <attribute id="service_id"/>
           </dependencies>
+          <sql>workgroup_id</sql>
+          <target_class>Team</target_class>
+          <is_null_allowed>false</is_null_allowed>
+          <on_target_delete>DEL_MANUAL</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="workgroup_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>workgroup_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
         </field>
-        <field name="workgroup_name" xsi:type="AttributeExternalField" extkey_attcode="workgroup_id" target_attcode="name"/>
-        <field name="agent_id" xsi:type="AttributeExternalKey" target_class="Person" jointype="" filter="SELECT Person AS p JOIN lnkTeamToContact AS l ON l.contact_id=p.id JOIN Team AS t ON l.team_id=t.id WHERE t.id = :this-&gt;workgroup_id" sql="agent_id" is_null_allowed="true" on_target_delete="DEL_MANUAL">
+        <field id="agent_id" xsi:type="AttributeExternalKey">
+          <filter><![CDATA[SELECT Person AS p JOIN lnkTeamToContact AS l ON l.contact_id=p.id JOIN Team AS t ON l.team_id=t.id WHERE t.id = :this->workgroup_id]]></filter>
           <dependencies>
-            <attribute name="workgroup_id"/>
+            <attribute id="workgroup_id"/>
           </dependencies>
+          <sql>agent_id</sql>
+          <target_class>Person</target_class>
+          <is_null_allowed>true</is_null_allowed>
+          <on_target_delete>DEL_MANUAL</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="agent_name" xsi:type="AttributeExternalField">
+          <extkey_attcode>agent_id</extkey_attcode>
+          <target_attcode>name</target_attcode>
+        </field>
+        <field id="agent_email" xsi:type="AttributeExternalField">
+          <extkey_attcode>agent_id</extkey_attcode>
+          <target_attcode>email</target_attcode>
+        </field>
+        <field id="related_change_id" xsi:type="AttributeExternalKey">
+          <sql>related_change_id</sql>
+          <target_class>Change</target_class>
+          <is_null_allowed>true</is_null_allowed>
+          <on_target_delete>DEL_MANUAL</on_target_delete>
+          <jointype></jointype>
+        </field>
+        <field id="related_change_ref" xsi:type="AttributeExternalField">
+          <extkey_attcode>related_change_id</extkey_attcode>
+          <target_attcode>ref</target_attcode>
+        </field>
+        <field id="close_date" xsi:type="AttributeDateTime">
+          <sql>close_date</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="last_update" xsi:type="AttributeDateTime">
+          <sql>last_update</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="assignment_date" xsi:type="AttributeDateTime">
+          <sql>assignment_date</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="resolution_date" xsi:type="AttributeDateTime">
+          <sql>resolution_date</sql>
+          <default_value></default_value>
+          <is_null_allowed>true</is_null_allowed>
+        </field>
+        <field id="knownerrors_list" xsi:type="AttributeLinkedSet">
+          <linked_class>KnownError</linked_class>
+          <ext_key_to_me>problem_id</ext_key_to_me>
+          <count_min>0</count_min>
+          <count_max>0</count_max>
         </field>
-        <field name="agent_name" xsi:type="AttributeExternalField" extkey_attcode="agent_id" target_attcode="name"/>
-        <field name="agent_email" xsi:type="AttributeExternalField" extkey_attcode="agent_id" target_attcode="email"/>
-        <field name="related_change_id" xsi:type="AttributeExternalKey" target_class="Change" jointype="" sql="related_change_id" is_null_allowed="true" on_target_delete="DEL_MANUAL"/>
-        <field name="related_change_ref" xsi:type="AttributeExternalField" extkey_attcode="related_change_id" target_attcode="ref"/>
-        <field name="close_date" xsi:type="AttributeDateTime" sql="close_date" default_value="" is_null_allowed="true"/>
-        <field name="last_update" xsi:type="AttributeDateTime" sql="last_update" default_value="" is_null_allowed="true"/>
-        <field name="assignment_date" xsi:type="AttributeDateTime" sql="assignment_date" default_value="" is_null_allowed="true"/>
-        <field name="resolution_date" xsi:type="AttributeDateTime" sql="resolution_date" default_value="" is_null_allowed="true"/>
-        <field name="knownerrors_list" xsi:type="AttributeLinkedSet" linked_class="KnownError" ext_key_to_me="problem_id" count_min="0" count_max="0"/>
       </fields>
-      <lifecycle attribute="status">
+      <lifecycle>
+        <attribute>status</attribute>
         <stimuli>
-          <stimulus name="ev_assign" type="StimulusUserAction"/>
-          <stimulus name="ev_reassign" type="StimulusUserAction"/>
-          <stimulus name="ev_resolve" type="StimulusUserAction"/>
-          <stimulus name="ev_close" type="StimulusUserAction"/>
+          <stimulus id="ev_assign" xsi:type="StimulusUserAction"/>
+          <stimulus id="ev_reassign" xsi:type="StimulusUserAction"/>
+          <stimulus id="ev_resolve" xsi:type="StimulusUserAction"/>
+          <stimulus id="ev_close" xsi:type="StimulusUserAction"/>
         </stimuli>
         <states>
-          <state name="new">
+          <state id="new">
             <flags>
-              <attribute name="ref" read_only="1"/>
-              <attribute name="title"/>
-              <attribute name="description" must_change="1"/>
-              <attribute name="ticket_log" hidden="1"/>
-              <attribute name="start_date" read_only="1"/>
-              <attribute name="document_list"/>
-              <attribute name="ci_list"/>
-              <attribute name="contact_list"/>
-              <attribute name="incident_list"/>
-              <attribute name="status"/>
-              <attribute name="org_id" must_change="1"/>
-              <attribute name="org_name"/>
-              <attribute name="service_id" must_change="1"/>
-              <attribute name="service_name"/>
-              <attribute name="servicesubcategory_id" must_change="1"/>
-              <attribute name="servicesubcategory_name"/>
-              <attribute name="product" must_prompt="1"/>
-              <attribute name="impact" must_change="1"/>
-              <attribute name="urgency" must_change="1"/>
-              <attribute name="priority" read_only="1"/>
-              <attribute name="workgroup_id" must_change="1"/>
-              <attribute name="workgroup_name"/>
-              <attribute name="agent_id" hidden="1"/>
-              <attribute name="agent_name"/>
-              <attribute name="agent_email" hidden="1"/>
-              <attribute name="related_change_id" hidden="1"/>
-              <attribute name="related_change_ref"/>
-              <attribute name="close_date" hidden="1"/>
-              <attribute name="last_update" read_only="1"/>
-              <attribute name="assignment_date" hidden="1"/>
-              <attribute name="resolution_date" hidden="1"/>
-              <attribute name="knownerrors_list"/>
-              <attribute name="related_change_id_finalclass_recall"/>
+              <attribute id="ref">
+                <read_only/>
+              </attribute>
+              <attribute id="description">
+                <must_change/>
+              </attribute>
+              <attribute id="ticket_log">
+                <hidden/>
+              </attribute>
+              <attribute id="start_date">
+                <read_only/>
+              </attribute>
+              <attribute id="org_id">
+                <must_change/>
+              </attribute>
+              <attribute id="service_id">
+                <must_change/>
+              </attribute>
+              <attribute id="servicesubcategory_id">
+                <must_change/>
+              </attribute>
+              <attribute id="product">
+                <must_prompt/>
+              </attribute>
+              <attribute id="impact">
+                <must_change/>
+              </attribute>
+              <attribute id="urgency">
+                <must_change/>
+              </attribute>
+              <attribute id="priority">
+                <read_only/>
+              </attribute>
+              <attribute id="workgroup_id">
+                <must_change/>
+              </attribute>
+              <attribute id="agent_id">
+                <hidden/>
+              </attribute>
+              <attribute id="agent_email">
+                <hidden/>
+              </attribute>
+              <attribute id="related_change_id">
+                <hidden/>
+              </attribute>
+              <attribute id="close_date">
+                <hidden/>
+              </attribute>
+              <attribute id="last_update">
+                <read_only/>
+              </attribute>
+              <attribute id="assignment_date">
+                <hidden/>
+              </attribute>
+              <attribute id="resolution_date">
+                <hidden/>
+              </attribute>
             </flags>
             <transitions>
-              <transition stimulus="ev_assign" target="assigned">
+              <transition>
+                <stimulus>ev_assign</stimulus>
+                <target>assigned</target>
                 <actions>
-                  <action verb="SetAssignedDate"/>
+                  <action>
+                    <verb>SetAssignedDate</verb>
+                  </action>
                 </actions>
               </transition>
             </transitions>
           </state>
-          <state name="assigned">
+          <state id="assigned">
             <flags>
-              <attribute name="ref" read_only="1"/>
-              <attribute name="title" read_only="1"/>
-              <attribute name="description" read_only="1"/>
-              <attribute name="ticket_log"/>
-              <attribute name="start_date" read_only="1"/>
-              <attribute name="document_list"/>
-              <attribute name="ci_list"/>
-              <attribute name="contact_list"/>
-              <attribute name="incident_list"/>
-              <attribute name="status"/>
-              <attribute name="org_id" read_only="1"/>
-              <attribute name="org_name"/>
-              <attribute name="service_id"/>
-              <attribute name="service_name"/>
-              <attribute name="servicesubcategory_id"/>
-              <attribute name="servicesubcategory_name"/>
-              <attribute name="product"/>
-              <attribute name="impact"/>
-              <attribute name="urgency"/>
-              <attribute name="priority" read_only="1"/>
-              <attribute name="workgroup_id" mandatory="1" must_prompt="1"/>
-              <attribute name="workgroup_name"/>
-              <attribute name="agent_id" mandatory="1" must_prompt="1"/>
-              <attribute name="agent_name"/>
-              <attribute name="agent_email" read_only="1"/>
-              <attribute name="related_change_id"/>
-              <attribute name="related_change_ref"/>
-              <attribute name="close_date" hidden="1"/>
-              <attribute name="last_update" read_only="1"/>
-              <attribute name="assignment_date" read_only="1"/>
-              <attribute name="resolution_date" hidden="1"/>
-              <attribute name="knownerrors_list"/>
-              <attribute name="related_change_id_finalclass_recall"/>
+              <attribute id="ref">
+                <read_only/>
+              </attribute>
+              <attribute id="title">
+                <read_only/>
+              </attribute>
+              <attribute id="description">
+                <read_only/>
+              </attribute>
+              <attribute id="start_date">
+                <read_only/>
+              </attribute>
+              <attribute id="org_id">
+                <read_only/>
+              </attribute>
+              <attribute id="priority">
+                <read_only/>
+              </attribute>
+              <attribute id="workgroup_id">
+                <mandatory/>
+                <must_prompt/>
+              </attribute>
+              <attribute id="agent_id">
+                <mandatory/>
+                <must_prompt/>
+              </attribute>
+              <attribute id="agent_email">
+                <read_only/>
+              </attribute>
+              <attribute id="close_date">
+                <hidden/>
+              </attribute>
+              <attribute id="last_update">
+                <read_only/>
+              </attribute>
+              <attribute id="assignment_date">
+                <read_only/>
+              </attribute>
+              <attribute id="resolution_date">
+                <hidden/>
+              </attribute>
             </flags>
             <transitions>
-              <transition stimulus="ev_reassign" target="assigned">
+              <transition>
+                <stimulus>ev_reassign</stimulus>
+                <target>assigned</target>
                 <actions/>
               </transition>
-              <transition stimulus="ev_resolve" target="resolved">
+              <transition>
+                <stimulus>ev_resolve</stimulus>
+                <target>resolved</target>
                 <actions>
-                  <action verb="SetResolveDate"/>
+                  <action>
+                    <verb>SetResolveDate</verb>
+                  </action>
                 </actions>
               </transition>
             </transitions>
           </state>
-          <state name="resolved">
+          <state id="resolved">
             <flags>
-              <attribute name="ref" read_only="1"/>
-              <attribute name="title" read_only="1"/>
-              <attribute name="description" read_only="1"/>
-              <attribute name="ticket_log"/>
-              <attribute name="start_date" read_only="1"/>
-              <attribute name="document_list"/>
-              <attribute name="ci_list"/>
-              <attribute name="contact_list"/>
-              <attribute name="incident_list"/>
-              <attribute name="status"/>
-              <attribute name="org_id" read_only="1"/>
-              <attribute name="org_name"/>
-              <attribute name="service_id" read_only="1"/>
-              <attribute name="service_name"/>
-              <attribute name="servicesubcategory_id" read_only="1"/>
-              <attribute name="servicesubcategory_name"/>
-              <attribute name="product" read_only="1"/>
-              <attribute name="impact" read_only="1"/>
-              <attribute name="urgency" read_only="1"/>
-              <attribute name="priority" read_only="1"/>
-              <attribute name="workgroup_id" read_only="1"/>
-              <attribute name="workgroup_name"/>
-              <attribute name="agent_id" read_only="1"/>
-              <attribute name="agent_name"/>
-              <attribute name="agent_email" read_only="1"/>
-              <attribute name="related_change_id"/>
-              <attribute name="related_change_ref"/>
-              <attribute name="close_date" hidden="1"/>
-              <attribute name="last_update" read_only="1"/>
-              <attribute name="assignment_date" read_only="1"/>
-              <attribute name="resolution_date" hidden="1"/>
-              <attribute name="knownerrors_list"/>
-              <attribute name="related_change_id_finalclass_recall"/>
+              <attribute id="ref">
+                <read_only/>
+              </attribute>
+              <attribute id="title">
+                <read_only/>
+              </attribute>
+              <attribute id="description">
+                <read_only/>
+              </attribute>
+              <attribute id="start_date">
+                <read_only/>
+              </attribute>
+              <attribute id="org_id">
+                <read_only/>
+              </attribute>
+              <attribute id="service_id">
+                <read_only/>
+              </attribute>
+              <attribute id="servicesubcategory_id">
+                <read_only/>
+              </attribute>
+              <attribute id="product">
+                <read_only/>
+              </attribute>
+              <attribute id="impact">
+                <read_only/>
+              </attribute>
+              <attribute id="urgency">
+                <read_only/>
+              </attribute>
+              <attribute id="priority">
+                <read_only/>
+              </attribute>
+              <attribute id="workgroup_id">
+                <read_only/>
+              </attribute>
+              <attribute id="agent_id">
+                <read_only/>
+              </attribute>
+              <attribute id="agent_email">
+                <read_only/>
+              </attribute>
+              <attribute id="close_date">
+                <hidden/>
+              </attribute>
+              <attribute id="last_update">
+                <read_only/>
+              </attribute>
+              <attribute id="assignment_date">
+                <read_only/>
+              </attribute>
+              <attribute id="resolution_date">
+                <hidden/>
+              </attribute>
             </flags>
             <transitions>
-              <transition stimulus="ev_reassign" target="assigned">
+              <transition>
+                <stimulus>ev_reassign</stimulus>
+                <target>assigned</target>
                 <actions/>
               </transition>
-              <transition stimulus="ev_close" target="closed">
+              <transition>
+                <stimulus>ev_close</stimulus>
+                <target>closed</target>
                 <actions>
-                  <action verb="SetClosureDate"/>
+                  <action>
+                    <verb>SetClosureDate</verb>
+                  </action>
                 </actions>
               </transition>
             </transitions>
           </state>
-          <state name="closed">
+          <state id="closed">
             <flags>
-              <attribute name="ref" read_only="1"/>
-              <attribute name="title" read_only="1"/>
-              <attribute name="description" read_only="1"/>
-              <attribute name="ticket_log" read_only="1"/>
-              <attribute name="start_date" read_only="1"/>
-              <attribute name="document_list"/>
-              <attribute name="ci_list"/>
-              <attribute name="contact_list"/>
-              <attribute name="incident_list"/>
-              <attribute name="status"/>
-              <attribute name="org_id" read_only="1"/>
-              <attribute name="org_name"/>
-              <attribute name="service_id" read_only="1"/>
-              <attribute name="service_name"/>
-              <attribute name="servicesubcategory_id" read_only="1"/>
-              <attribute name="servicesubcategory_name"/>
-              <attribute name="product" read_only="1"/>
-              <attribute name="impact" read_only="1"/>
-              <attribute name="urgency" read_only="1"/>
-              <attribute name="priority" read_only="1"/>
-              <attribute name="workgroup_id" read_only="1"/>
-              <attribute name="workgroup_name"/>
-              <attribute name="agent_id" read_only="1"/>
-              <attribute name="agent_name"/>
-              <attribute name="agent_email" read_only="1"/>
-              <attribute name="related_change_id"/>
-              <attribute name="related_change_ref"/>
-              <attribute name="close_date" read_only="1"/>
-              <attribute name="last_update" read_only="1"/>
-              <attribute name="assignment_date" read_only="1"/>
-              <attribute name="resolution_date" hidden="1"/>
-              <attribute name="knownerrors_list"/>
-              <attribute name="related_change_id_finalclass_recall"/>
+              <attribute id="ref">
+                <read_only/>
+              </attribute>
+              <attribute id="title">
+                <read_only/>
+              </attribute>
+              <attribute id="description">
+                <read_only/>
+              </attribute>
+              <attribute id="ticket_log">
+                <read_only/>
+              </attribute>
+              <attribute id="start_date">
+                <read_only/>
+              </attribute>
+              <attribute id="org_id">
+                <read_only/>
+              </attribute>
+              <attribute id="service_id">
+                <read_only/>
+              </attribute>
+              <attribute id="servicesubcategory_id">
+                <read_only/>
+              </attribute>
+              <attribute id="product">
+                <read_only/>
+              </attribute>
+              <attribute id="impact">
+                <read_only/>
+              </attribute>
+              <attribute id="urgency">
+                <read_only/>
+              </attribute>
+              <attribute id="priority">
+                <read_only/>
+              </attribute>
+              <attribute id="workgroup_id">
+                <read_only/>
+              </attribute>
+              <attribute id="agent_id">
+                <read_only/>
+              </attribute>
+              <attribute id="agent_email">
+                <read_only/>
+              </attribute>
+              <attribute id="close_date">
+                <read_only/>
+              </attribute>
+              <attribute id="last_update">
+                <read_only/>
+              </attribute>
+              <attribute id="assignment_date">
+                <read_only/>
+              </attribute>
+              <attribute id="resolution_date">
+                <hidden/>
+              </attribute>
             </flags>
             <transitions/>
           </state>
         </states>
       </lifecycle>
       <methods>
-        <method name="SetAssignedDate" static="false" access="public" type="LifecycleAction"><![CDATA[        public function SetAssignedDate($sStimulusCode)
+        <method id="SetAssignedDate">
+          <static>false</static>
+          <access>public</access>
+          <type>LifecycleAction</type>
+          <code><![CDATA[        public function SetAssignedDate($sStimulusCode)
         {
                 $this->Set('assignment_date', time());
                 return true;
-        }]]></method>
-        <method name="SetResolveDate" static="false" access="public" type="LifecycleAction"><![CDATA[        public function SetResolveDate($sStimulusCode)
+        }]]></code>
+        </method>
+        <method id="SetResolveDate">
+          <static>false</static>
+          <access>public</access>
+          <type>LifecycleAction</type>
+          <code><![CDATA[        public function SetResolveDate($sStimulusCode)
         {
                 $this->Set('resolution_date', time());
                 return true;
-        }]]></method>
-        <method name="SetClosureDate" static="false" access="public" type="LifecycleAction"><![CDATA[        public function SetClosureDate($sStimulusCode)
+        }]]></code>
+        </method>
+        <method id="SetClosureDate">
+          <static>false</static>
+          <access>public</access>
+          <type>LifecycleAction</type>
+          <code><![CDATA[        public function SetClosureDate($sStimulusCode)
         {
                 $this->Set('close_date', time());
                 return true;
-        }]]></method>
-        <method name="ComputePriority" static="false" access="public" type="LifecycleAction"><comment><![CDATA[/** Compute the priority of the ticket based on its impact and urgency
+        }]]></code>
+        </method>
+        <method id="ComputePriority">
+          <comment>/** Compute the priority of the ticket based on its impact and urgency
          * @return integer The priority of the ticket 1(high) .. 3(low)
-         */]]></comment><![CDATA[        public function ComputePriority()
+         */</comment>
+          <static>false</static>
+          <access>public</access>
+          <type>LifecycleAction</type>
+          <code><![CDATA[        public function ComputePriority()
         {
                 // priority[impact][urgency]
                 $aPriorities = array(
@@ -325,8 +543,13 @@
                 );
                 $iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
                 return $iPriority;              
-        }]]></method>
-        <method name="ComputeValues" static="false" access="public" type="Overload-DBObject"><![CDATA[	public function ComputeValues()
+        }]]></code>
+        </method>
+        <method id="ComputeValues">
+          <static>false</static>
+          <access>public</access>
+          <type>Overload-DBObject</type>
+          <code><![CDATA[	public function ComputeValues()
 	{
 		// Compute the priority of the ticket
 		$this->Set('priority', $this->ComputePriority());
@@ -343,7 +566,8 @@
 			$sName = sprintf('P-%06d', $iKey);
 			$this->Set('ref', $sName);
 		}
-	}]]></method>
+	}]]></code>
+        </method>
       </methods>
       <presentation>
         <details>
@@ -352,9 +576,9 @@
             <item>ci_list</item>
             <item>contact_list</item>
             <item>incident_list</item>
-            <item key="col:col1">
+            <item id="col:col1">
               <items>
-                <item key="fieldset:Ticket:baseinfo">
+                <item id="fieldset:Ticket:baseinfo">
                   <items>
                     <item>ref</item>
                     <item>title</item>
@@ -366,7 +590,7 @@
                     <item>product</item>
                   </items>
                 </item>
-                <item key="fieldset:Ticket:moreinfo">
+                <item id="fieldset:Ticket:moreinfo">
                   <items>
                     <item>impact</item>
                     <item>urgency</item>
@@ -375,9 +599,9 @@
                 </item>
               </items>
             </item>
-            <item key="col:col2">
+            <item id="col:col2">
               <items>
-                <item key="fieldset:Ticket:date">
+                <item id="fieldset:Ticket:date">
                   <items>
                     <item>start_date</item>
                     <item>last_update</item>
@@ -385,13 +609,13 @@
                     <item>close_date</item>
                   </items>
                 </item>
-                <item key="fieldset:Ticket:contact">
+                <item id="fieldset:Ticket:contact">
                   <items>
                     <item>workgroup_id</item>
                     <item>agent_id</item>
                   </items>
                 </item>
-                <item key="fieldset:Ticket:relation">
+                <item id="fieldset:Ticket:relation">
                   <items>
                     <item>related_change_id</item>
                   </items>
@@ -434,31 +658,31 @@
   </classes>
   <menus>
     <menu id="Problem:Overview" xsi:type="TemplateMenuNode">
-      <rank value="0"/>
-      <parent value="ProblemManagement"/>
-      <template_file value="overview.html"/>
+      <rank>0</rank>
+      <parent>ProblemManagement</parent>
+      <template_file>overview.html</template_file>
     </menu>
     <menu id="NewProblem" xsi:type="NewObjectMenuNode">
-      <rank value="1"/>
-      <parent value="ProblemManagement"/>
-      <class value="Problem"/>
+      <rank>1</rank>
+      <parent>ProblemManagement</parent>
+      <class>Problem</class>
     </menu>
     <menu id="SearchProblems" xsi:type="SearchMenuNode">
-      <rank value="2"/>
-      <parent value="ProblemManagement"/>
-      <class value="Problem"/>
+      <rank>2</rank>
+      <parent>ProblemManagement</parent>
+      <class>Problem</class>
     </menu>
     <menu id="Problem:MyProblems" xsi:type="OQLMenuNode">
-      <rank value="1"/>
-      <parent value="Problem:Shortcuts"/>
-      <oql value="SELECT Problem WHERE agent_id = :current_contact_id AND status NOT IN (&quot;closed&quot;, &quot;resolved&quot;)"/>
-      <do_search value=""/>
+      <rank>1</rank>
+      <parent>Problem:Shortcuts</parent>
+      <oql><![CDATA[SELECT Problem WHERE agent_id = :current_contact_id AND status NOT IN ("closed", "resolved")]]></oql>
+      <do_search></do_search>
     </menu>
     <menu id="Problem:OpenProblems" xsi:type="OQLMenuNode">
-      <rank value="2"/>
-      <parent value="Problem:Shortcuts"/>
-      <oql value="SELECT Problem WHERE status IN (&quot;new&quot;, &quot;assigned&quot;, &quot;resolved&quot;)"/>
-      <do_search value=""/>
+      <rank>2</rank>
+      <parent>Problem:Shortcuts</parent>
+      <oql><![CDATA[SELECT Problem WHERE status IN ("new", "assigned", "resolved")]]></oql>
+      <do_search></do_search>
     </menu>
   </menus>
 </itop_design>

Різницю між файлами не показано, бо вона завелика
+ 634 - 358
datamodel/itop-request-mgmt-1.0.0/datamodel.itop-request-mgmt.xml


Різницю між файлами не показано, бо вона завелика
+ 589 - 143
datamodel/itop-service-mgmt-1.0.0/datamodel.itop-service-mgmt.xml


Різницю між файлами не показано, бо вона завелика
+ 833 - 397
datamodel/itop-tickets-1.0.0/datamodel.itop-tickets.xml


+ 101 - 214
setup/compiler.class.inc.php

@@ -141,14 +141,13 @@ EOF;
 		
 				foreach($oClasses as $oClass)
 				{
-					$sClass = $oClass->getAttribute("name");
 					try
 					{
 						$this->CompileClass($oClass, $sResultFile, $sRelativeDir, $oP);
 					}
 					catch (ssDOMFormatException $e)
 					{
-						$sClass = $oClass->getAttribute("name");
+						$sClass = $oClass->getAttribute("id");
 						throw new Exception("Failed to process class '$sClass', from '$sModuleRootDir': ".$e->getMessage());
 					}
 				}
@@ -175,9 +174,9 @@ EOF;
 				$aMenusToLoad = array();
 				foreach($oMenus as $oMenu)
 				{
-					if ($oParent = $this->GetOptionalElement($oMenu, 'parent'))
+					if ($sParent = $oMenu->GetChildText('parent', null))
 					{
-						$aMenusToLoad[] = $oParent->GetAttribute('value');
+						$aMenusToLoad[] = $sParent;
 					}
 					// Note: the order matters: the parents must be defined BEFORE
 					$aMenusToLoad[] = $oMenu->GetAttribute('id');
@@ -192,7 +191,7 @@ EOF;
 					}
 					catch (ssDOMFormatException $e)
 					{
-						$sMenu = $oMenu->getAttribute("name");
+						$sMenu = $oMenu->getAttribute("id");
 						throw new Exception("Failed to process menu '$sMenu', from '$sModuleRootDir': ".$e->getMessage());
 					}
 				}
@@ -260,104 +259,6 @@ EOF;
 		}
 	}
 	
-	
-	/**
-	 * Helper to browse the DOM -could be factorized in ModelFactory
-	 * Returns the node directly under the given node, and that is supposed to be always present and unique 
-	 */ 
-	protected function GetUniqueElement($oDOMNode, $sTagName, $bMustExist = true)
-	{
-		$oNode = null;
-		if ($oDOMNode->hasChildNodes())
-		{
-			foreach($oDOMNode->childNodes as $oChildNode)
-			{
-				if ($oChildNode->nodeName == $sTagName)
-				{
-					$oNode = $oChildNode;
-					break;
-				}
-			}
-		}
-		if ($bMustExist && is_null($oNode))
-		{
-			throw new DOMFormatException('Missing unique tag: '.$sTagName);
-		}
-		return $oNode;
-	}
-	
-	/**
-	 * Helper to browse the DOM -could be factorized in ModelFactory
-	 * Returns the node directly under the given node, or null is missing 
-	 */ 
-	protected function GetOptionalElement($oDOMNode, $sTagName)
-	{
-		return $this->GetUniqueElement($oDOMNode, $sTagName, false);
-	}
-	
-	
-	/**
-	 * Helper to browse the DOM -could be factorized in ModelFactory
-	 * Returns the TEXT of the given node (possibly from several subnodes) 
-	 */ 
-	protected function GetNodeText($oNode)
-	{
-		$sText = '';
-		if ($oNode->hasChildNodes())
-		{
-			foreach($oNode->childNodes as $oChildNode)
-			{
-				if ($oChildNode instanceof DOMCharacterData) // Base class of DOMText and DOMCdataSection
-				{
-					$sText .= $oChildNode->wholeText;
-				}
-			}
-		}
-		return $sText;
-	}
-	
-	/**
-	 * Helper to browse the DOM -could be factorized in ModelFactory
-	 * Assumes the given node to be either a text or
-	 * <items>
-	 *   <item [key]="..."]>value<item>
-	 *   <item [key]="..."]>value<item>
-	 * </items>
-	 * where value can be the either a text or an array of items... recursively 
-	 * Returns a PHP array 
-	 */ 
-	protected function GetNodeAsArrayOfItems($oNode)
-	{
-		$oItems = $this->GetOptionalElement($oNode, 'items');
-		if ($oItems)
-		{
-			$res = array();
-			if ($oItems->hasChildNodes())
-			{
-				foreach($oItems->childNodes as $oItem)
-				{
-					// When an attribute is msising
-					if ($oItem->hasAttributes() && $oItem->hasAttribute('key'))
-					{
-						$key = $oItem->getAttribute('key');
-						$res[$key] = $this->GetNodeAsArrayOfItems($oItem);
-					}
-					else
-					{
-						$res[] = $this->GetNodeAsArrayOfItems($oItem);
-					}
-				}
-			}
-		}
-		else
-		{
-			$res = $this->GetNodeText($oNode);
-		}
-		return $res;
-	}
-	
-	
-	
 	/**
 	 * Helper to format the flags for an attribute, in a given state
 	 * @param object $oAttNode DOM node containing the information to build the flags
@@ -376,7 +277,7 @@ EOF;
 		$aFlags = array();
 		foreach ($aNodeAttributeToFlag as $sNodeAttribute => $sFlag)
 		{
-			$bFlag = ($oAttNode->GetAttribute($sNodeAttribute) == '1');
+			$bFlag = ($oAttNode->GetOptionalElement($sNodeAttribute) != null);
 			if ($bFlag)
 			{
 				$aFlags[] = $sFlag;
@@ -426,22 +327,22 @@ EOF;
 
 	protected function CompileClass($oClass, $sResFile, $sModuleRelativeDir, $oP)
 	{
-		$sClass = $oClass->getAttribute('name');
-		$oProperties = $this->GetUniqueElement($oClass, 'properties');
+		$sClass = $oClass->getAttribute('id');
+		$oProperties = $oClass->GetUniqueElement('properties');
 	
 		// Class caracteristics
 		//
 		$aClassParams = array();
-		$aClassParams['category'] = "'".$oClass->getAttribute('category')."'";
+		$aClassParams['category'] = "'".$oProperties->GetChildText('category')."'";
 		$aClassParams['key_type'] = "'autoincrement'";
 	
-		$oNaming = $this->GetUniqueElement($oProperties, 'naming');
-		$oNameAttributes = $this->GetUniqueElement($oNaming, 'attributes');
+		$oNaming = $oProperties->GetUniqueElement('naming');
+		$oNameAttributes = $oNaming->GetUniqueElement('attributes');
 		$oAttributes = $oNameAttributes->getElementsByTagName('attribute');
 		$aNameAttCodes = array();
 		foreach($oAttributes as $oAttribute)
 		{
-			$aNameAttCodes[] = $oAttribute->getAttribute('name');
+			$aNameAttCodes[] = $oAttribute->getAttribute('id');
 		}
 		if (count($aNameAttCodes) > 1)
 		{
@@ -459,10 +360,10 @@ EOF;
 		}
 		$aClassParams['name_attcode'] = $sNameAttCode;
 	
-		$oLifecycle = $this->GetOptionalElement($oClass, 'lifecycle');
+		$oLifecycle = $oClass->GetOptionalElement('lifecycle');
 		if ($oLifecycle)
 		{
-			$sStateAttCode = $oLifecycle->getAttribute('attribute');
+			$sStateAttCode = $oLifecycle->GetChildText('attribute');
 		}
 		else
 		{
@@ -470,43 +371,41 @@ EOF;
 		}
 		$aClassParams['state_attcode'] = "'$sStateAttCode'";
 	
-		$oReconciliation = $this->GetUniqueElement($oProperties, 'reconciliation');
+		$oReconciliation = $oProperties->GetUniqueElement('reconciliation');
 		$oReconcAttributes = $oReconciliation->getElementsByTagName('attribute');
 		$aReconcAttCodes = array();
 		foreach($oReconcAttributes as $oAttribute)
 		{
-			$aReconcAttCodes[] = $oAttribute->getAttribute('name');
+			$aReconcAttCodes[] = $oAttribute->getAttribute('id');
 		}
 		$sReconcKeys = "array('".implode("', '", $aReconcAttCodes)."')";
 		$aClassParams['reconc_keys'] = $sReconcKeys;
 	
-		$aClassParams['db_table'] = "'".$oClass->getAttribute('db_table')."'";
-		$aClassParams['db_key_field'] = "'".$oClass->getAttribute('db_key_field')."'";
-		$aClassParams['db_finalclass_field'] = "'".$oClass->getAttribute('db_final_class_field')."'";
+		$aClassParams['db_table'] = "'".$oProperties->GetChildText('db_table')."'";
+		$aClassParams['db_key_field'] = "'".$oProperties->GetChildText('db_key_field')."'";
+		$aClassParams['db_finalclass_field'] = "'".$oProperties->GetChildText('db_final_class_field')."'";
 	
-		$oDisplayTemplate = $this->GetOptionalElement($oProperties, 'display_template');
-		if ($oDisplayTemplate && (strlen($oDisplayTemplate->textContent) > 0))
+		if (($sDisplayTemplate = $oProperties->GetChildText('display_template')) && (strlen($sDisplayTemplate) > 0))
 		{
-			$sDisplayTemplate = $sModuleRelativeDir.'/'.$oDisplayTemplate->textContent;
+			$sDisplayTemplate = $sModuleRelativeDir.'/'.$sDisplayTemplate;
 			$aClassParams['display_template'] = "utils::GetAbsoluteUrlModulesRoot().'$sDisplayTemplate'";
 		}
 	
-		$oIcon = $this->GetOptionalElement($oProperties, 'icon');
-		if ($oIcon && (strlen($oIcon->textContent) > 0))
+		if (($sIcon = $oProperties->GetChildText('icon')) && (strlen($sIcon) > 0))
 		{
-			$sIcon = $sModuleRelativeDir.'/'.$oIcon->textContent;
+			$sIcon = $sModuleRelativeDir.'/'.$sIcon;
 			$aClassParams['icon'] = "utils::GetAbsoluteUrlModulesRoot().'$sIcon'";
 		}
 	
-		$oOrder = $this->GetOptionalElement($oProperties, 'order');
+		$oOrder = $oProperties->GetOptionalElement('order');
 		if ($oOrder)
 		{
-			$oColumnsNode = $this->GetUniqueElement($oOrder, 'columns');
+			$oColumnsNode = $oOrder->GetUniqueElement('columns');
 			$oColumns = $oColumnsNode->getElementsByTagName('column');
 			$aSortColumns = array();
 			foreach($oColumns as $oColumn)
 			{
-				$aSortColumns[] = "'".$oColumn->getAttribute('name')."' => ".(($oColumn->getAttribute('ascending') == 'true') ? 'true' : 'false');
+				$aSortColumns[] = "'".$oColumn->getAttribute('id')."' => ".(($oColumn->getAttribute('ascending') == 'true') ? 'true' : 'false');
 			}
 			if (count($aSortColumns) > 0)
 			{
@@ -526,15 +425,7 @@ EOF;
 	
 		// Comment on top of the class declaration
 		//
-		$oComment = $this->GetOptionalElement($oProperties, 'comment');
-		if ($oComment)
-		{
-			$sCodeComment = $oComment->textContent;
-		}
-		else
-		{
-			$sCodeComment = '';
-		}
+		$sCodeComment = $oProperties->GetChildText('comment');
 	
 		// Fields
 		//
@@ -542,17 +433,17 @@ EOF;
 		foreach($this->oFactory->ListFields($oClass) as $oField)
 		{
 			// $oField
-			$sAttCode = $oField->getAttribute('name');
+			$sAttCode = $oField->getAttribute('id');
 			$sAttType = $oField->getAttribute('xsi:type');
 	
 			$aDependencies = array();
-			$oDependencies = $this->GetOptionalElement($oField, 'dependencies');
+			$oDependencies = $oField->GetOptionalElement('dependencies');
 			if (!is_null($oDependencies))
 			{
 				$oDepNodes = $oDependencies->getElementsByTagName('attribute');
 				foreach($oDepNodes as $oDepAttribute)
 				{
-					$aDependencies[] = "'".$oDepAttribute->getAttribute('name')."'";
+					$aDependencies[] = "'".$oDepAttribute->getAttribute('id')."'";
 				}
 			}
 			$sDependencies = 'array('.implode(', ', $aDependencies).')';
@@ -561,31 +452,30 @@ EOF;
 	
 			if ($sAttType == 'AttributeLinkedSetIndirect')
 			{
-				$aParameters['linked_class'] = "'".$oField->getAttribute('linked_class')."'";
-				$aParameters['ext_key_to_me'] = "'".$oField->getAttribute('ext_key_to_me')."'";
-				$aParameters['ext_key_to_remote'] = "'".$oField->getAttribute('ext_key_to_remote')."'";
+				$aParameters['linked_class'] = "'".$oField->GetChildText('linked_class')."'";
+				$aParameters['ext_key_to_me'] = "'".$oField->GetChildText('ext_key_to_me')."'";
+				$aParameters['ext_key_to_remote'] = "'".$oField->GetChildText('ext_key_to_remote')."'";
 	// todo - utile ?
 				$aParameters['allowed_values'] = 'null';
-				$aParameters['count_min'] = $oField->getAttribute('count_min');
-				$aParameters['count_max'] = $oField->getAttribute('count_max');
+				$aParameters['count_min'] = $oField->GetChildText('count_min');
+				$aParameters['count_max'] = $oField->GetChildText('count_max');
 				$aParameters['depends_on'] = $sDependencies;
 			}
 			elseif ($sAttType == 'AttributeLinkedSet')
 			{
-				$aParameters['linked_class'] = "'".$oField->getAttribute('linked_class')."'";
-				$aParameters['ext_key_to_me'] = "'".$oField->getAttribute('ext_key_to_me')."'";
+				$aParameters['linked_class'] = "'".$oField->GetChildText('linked_class')."'";
+				$aParameters['ext_key_to_me'] = "'".$oField->GetChildText('ext_key_to_me')."'";
 	// todo - utile ?
 				$aParameters['allowed_values'] = 'null';
-				$aParameters['count_min'] = $oField->getAttribute('count_min');
-				$aParameters['count_max'] = $oField->getAttribute('count_max');
+				$aParameters['count_min'] = $oField->GetChildText('count_min');
+				$aParameters['count_max'] = $oField->GetChildText('count_max');
 				$aParameters['depends_on'] = $sDependencies;
 			}
 			elseif ($sAttType == 'AttributeExternalKey')
 			{
-				$aParameters['targetclass'] = "'".$oField->getAttribute('target_class')."'";
-	// todo = v�rifier l'utilit�
+				$aParameters['targetclass'] = "'".$oField->GetChildText('target_class')."'";
 				$aParameters['jointype'] = 'null';
-				if (($sOql = $oField->getAttribute('filter')) != '')
+				if ($sOql = $oField->GetChildText('filter'))
 				{
 					$sEscapedOql = addslashes($sOql);
 					$aParameters['allowed_values'] = "new ValueSetObjects('$sEscapedOql')"; // or "new ValueSetObjects('SELECT xxxx')"
@@ -594,14 +484,14 @@ EOF;
 				{
 					$aParameters['allowed_values'] = 'null'; // or "new ValueSetObjects('SELECT xxxx')"
 				}
-				$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
-				$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
-				$aParameters['on_target_delete'] = $oField->getAttribute('on_target_delete');
+				$aParameters['sql'] = "'".$oField->GetChildText('sql')."'";
+				$aParameters['is_null_allowed'] = $oField->GetChildText('is_null_allowed') == 'true' ? 'true' : 'false';
+				$aParameters['on_target_delete'] = $oField->GetChildText('on_target_delete');
 				$aParameters['depends_on'] = $sDependencies;
 			}
 			elseif ($sAttType == 'AttributeHierarchicalKey')
 			{
-				if (($sOql = $oField->getAttribute('filter')) != '')
+				if ($sOql = $oField->GetChildText('filter'))
 				{
 					$sEscapedOql = addslashes($sOql);
 					$aParameters['allowed_values'] = "new ValueSetObjects('$sEscapedOql')"; // or "new ValueSetObjects('SELECT xxxx')"
@@ -610,29 +500,29 @@ EOF;
 				{
 					$aParameters['allowed_values'] = 'null'; // or "new ValueSetObjects('SELECT xxxx')"
 				}
-				$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
-				$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
-				$aParameters['on_target_delete'] = $oField->getAttribute('on_target_delete');
+				$aParameters['sql'] = "'".$oField->GetChildText('sql')."'";
+				$aParameters['is_null_allowed'] = $oField->GetChildText('is_null_allowed') == 'true' ? 'true' : 'false';
+				$aParameters['on_target_delete'] = $oField->GetChildText('on_target_delete');
 				$aParameters['depends_on'] = $sDependencies;
 			}
 			elseif ($sAttType == 'AttributeExternalField')
 			{
 				$aParameters['allowed_values'] = 'null';
-				$aParameters['extkey_attcode'] = "'".$oField->getAttribute('extkey_attcode')."'";
-				$aParameters['target_attcode'] = "'".$oField->getAttribute('target_attcode')."'";
+				$aParameters['extkey_attcode'] = "'".$oField->GetChildText('extkey_attcode')."'";
+				$aParameters['target_attcode'] = "'".$oField->GetChildText('target_attcode')."'";
 			}
 			elseif ($sAttType == 'AttributeURL')
 			{
-				$aParameters['target'] = "'".$oField->getAttribute('target')."'";
+				$aParameters['target'] = "'".$oField->GetChildText('target')."'";
 				$aParameters['allowed_values'] = 'null';
-				$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
-				$aParameters['default_value'] = "'".$oField->getAttribute('default_value')."'";
-				$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
+				$aParameters['sql'] = "'".$oField->GetChildText('sql')."'";
+				$aParameters['default_value'] = "'".$oField->GetChildText('default_value')."'";
+				$aParameters['is_null_allowed'] = $oField->GetChildText('is_null_allowed') == 'true' ? 'true' : 'false';
 				$aParameters['depends_on'] = $sDependencies;
 			}
 			elseif ($sAttType == 'AttributeEnum')
 			{
-				$oValues = $this->GetUniqueElement($oField, 'values');
+				$oValues = $oField->GetUniqueElement('values');
 				$oValueNodes = $oValues->getElementsByTagName('value');
 				$aValues = array();
 				foreach($oValueNodes as $oValue)
@@ -643,9 +533,9 @@ EOF;
 	//	new style... $sValues = 'array('.implode(', ', $aValues).')';
 				$sValues = '"'.implode(',', $aValues).'"';
 				$aParameters['allowed_values'] = "new ValueSetEnum($sValues)";
-				$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
-				$aParameters['default_value'] = "'".$oField->getAttribute('default_value')."'";
-				$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
+				$aParameters['sql'] = "'".$oField->GetChildText('sql')."'";
+				$aParameters['default_value'] = "'".$oField->GetChildText('default_value')."'";
+				$aParameters['is_null_allowed'] = $oField->GetChildText('is_null_allowed') == 'true' ? 'true' : 'false';
 				$aParameters['depends_on'] = $sDependencies;
 			}
 			elseif ($sAttType == 'AttributeBlob')
@@ -655,12 +545,12 @@ EOF;
 			else
 			{
 				$aParameters['allowed_values'] = 'null'; // or "new ValueSetEnum('SELECT xxxx')"
-				$aParameters['sql'] = "'".$oField->getAttribute('sql')."'";
-				$aParameters['default_value'] = "'".$oField->getAttribute('default_value')."'";
-				$aParameters['is_null_allowed'] = $oField->getAttribute('is_null_allowed') == 'true' ? 'true' : 'false';
+				$aParameters['sql'] = "'".$oField->GetChildText('sql')."'";
+				$aParameters['default_value'] = "'".$oField->GetChildText('default_value')."'";
+				$aParameters['is_null_allowed'] = $oField->GetChildText('is_null_allowed') == 'true' ? 'true' : 'false';
 				$aParameters['depends_on'] = $sDependencies;
 				
-				if ($sValidationPattern = $oField->getAttribute('validation_pattern'))
+				if ($sValidationPattern = $oField->GetChildText('validation_pattern'))
 				{
 					$aParameters['validation_pattern'] = '"'.addslashes($sValidationPattern).'"';
 				}
@@ -683,19 +573,19 @@ EOF;
 			$sLifecycle .= "\t\t// Lifecycle (status attribute: $sStateAttCode)\n";
 			$sLifecycle .= "\t\t//\n";
 	
-			$oStimuli = $this->GetUniqueElement($oLifecycle, 'stimuli');
+			$oStimuli = $oLifecycle->GetUniqueElement('stimuli');
 			foreach ($oStimuli->getElementsByTagName('stimulus') as $oStimulus)
 			{
-				$sStimulus = $oStimulus->getAttribute('name');
-				$sStimulusClass = $oStimulus->getAttribute('type');
+				$sStimulus = $oStimulus->getAttribute('id');
+				$sStimulusClass = $oStimulus->getAttribute('xsi:type');
 	
 				$sLifecycle .= "		MetaModel::Init_DefineStimulus(new ".$sStimulusClass."(\"".$sStimulus."\", array()));\n";
 			}
 	
-			$oStates = $this->GetUniqueElement($oLifecycle, 'states');
+			$oStates = $oLifecycle->GetUniqueElement('states');
 			foreach ($oStates->getElementsByTagName('state') as $oState)
 			{
-				$sState = $oState->getAttribute('name');
+				$sState = $oState->getAttribute('id');
 	
 				$sLifecycle .= "		MetaModel::Init_DefineState(\n";
 				$sLifecycle .= "			\"".$sState."\",\n";
@@ -703,13 +593,13 @@ EOF;
 				$sLifecycle .= "				\"attribute_inherit\" => '',\n";
 				$sLifecycle .= "				\"attribute_list\" => array(\n";
 	
-				$oFlags = $this->GetUniqueElement($oState, 'flags');
+				$oFlags = $oState->GetUniqueElement('flags');
 				foreach ($oFlags->getElementsByTagName('attribute') as $oAttributeNode)
 				{
 					$sFlags = $this->FlagsToPHP($oAttributeNode);
 					if (strlen($sFlags) > 0)
 					{
-						$sAttCode = $oAttributeNode->GetAttribute('name');
+						$sAttCode = $oAttributeNode->GetAttribute('id');
 						$sLifecycle .= "					'$sAttCode' => $sFlags,\n";
 					}
 				}
@@ -718,17 +608,17 @@ EOF;
 				$sLifecycle .= "			)\n";
 				$sLifecycle .= "		);\n";
 	
-				$oTransitions = $this->GetUniqueElement($oState, 'transitions');
+				$oTransitions = $oState->GetUniqueElement('transitions');
 				foreach ($oTransitions->getElementsByTagName('transition') as $oTransition)
 				{
-					$sStimulus = $oTransition->getAttribute('stimulus');
-					$sTargetState = $oTransition->getAttribute('target');
+					$sStimulus = $oTransition->GetChildText('stimulus');
+					$sTargetState = $oTransition->GetChildText('target');
 	
-					$oActions = $this->GetUniqueElement($oTransition, 'actions');
+					$oActions = $oTransition->GetUniqueElement('actions');
 					$aVerbs = array();
 					foreach ($oActions->getElementsByTagName('action') as $oAction)
 					{
-						$sVerb = $oAction->getAttribute('verb');
+						$sVerb = $oAction->GetChildText('verb');
 						$aVerbs[] = "'$sVerb'";
 					}
 					$sActions = implode(', ', $aVerbs);
@@ -745,14 +635,14 @@ EOF;
 			'list' => 'list'
 		);
 	
-		$oPresentation = $this->GetUniqueElement($oClass, 'presentation');
+		$oPresentation = $oClass->GetUniqueElement('presentation');
 		$sZlists = '';
 		foreach ($aListRef as $sListCode => $sListTag)
 		{
-			$oListNode = $this->GetOptionalElement($oPresentation, $sListTag);
+			$oListNode = $oPresentation->GetOptionalElement($sListTag);
 			if ($oListNode)
 			{
-				$aAttributes = $this->GetNodeAsArrayOfItems($oListNode);
+				$aAttributes = $oListNode->GetNodeAsArrayOfItems();
 		
 				$sZAttributes = var_export($aAttributes, true);
 				$sZlists .= "		MetaModel::Init_SetZListItems('$sListCode', $sZAttributes);\n";
@@ -761,14 +651,13 @@ EOF;
 	
 		// Methods
 		$sMethods = "";
-		$oMethods = $this->GetUniqueElement($oClass, 'methods');
+		$oMethods = $oClass->GetUniqueElement('methods');
 		foreach($oMethods->getElementsByTagName('method') as $oMethod)
 		{
-			$sMethodCode = $this->GetNodeText($oMethod);
-			$oMethodComment = $this->GetOptionalElement($oMethod, 'comment');
-			if ($oMethodComment)
+			$sMethodCode = $oMethod->GetChildText('code');
+			if ($sMethodComment = $oMethod->GetChildText('comment', null))
 			{
-				$sMethods .= "\n\t".$oMethodComment->textContent."\n".$sMethodCode."\n";
+				$sMethods .= "\n\t$sMethodComment\n".$sMethodCode."\n";
 			}
 			else
 			{
@@ -779,15 +668,15 @@ EOF;
 		// Let's make the whole class declaration
 		//
 		$sPHP = "\n\n$sCodeComment\n";
-		if ($oClass->getAttribute('abstract') == 'true')
+		if ($oProperties->GetChildText('abstract') == 'true')
 		{
-			$sPHP .= 'abstract class '.$oClass->getAttribute('name');
+			$sPHP .= 'abstract class '.$oClass->getAttribute('id');
 		}
 		else
 		{
-			$sPHP .= 'class '.$oClass->getAttribute('name');
+			$sPHP .= 'class '.$oClass->getAttribute('id');
 		}
-		$sPHP .= " extends ".$oClass->getAttribute('parent')."\n";
+		$sPHP .= " extends ".$oClass->GetUniqueElement('properties')->GetChildText('parent', 'DBObject')."\n";
 		$sPHP .=
 <<<EOF
 {
@@ -816,10 +705,9 @@ EOF;
 		$sMenuId = $oMenu->getAttribute("id");
 		$sMenuClass = $oMenu->getAttribute("xsi:type");
 
-		$oParent = $this->GetOptionalElement($oMenu, 'parent');
-		if ($oParent)
+		$sParent = $oMenu->GetChildText('parent', null);
+		if ($sParent)
 		{
-			$sParent = $oParent->GetAttribute('value');
 			$sParentSpec = "\$__comp_menus__['$sParent']->GetIndex()";
 		}
 		else
@@ -827,45 +715,44 @@ EOF;
 			$sParentSpec = '-1';
 		}
 
-		$fRank = $this->GetUniqueElement($oMenu, 'rank')->GetAttribute('value');
+		$fRank = $oMenu->GetChildText('rank');
 		switch($sMenuClass)
 		{
 		case 'WebPageMenuNode':
-			$sUrl = $this->GetUniqueElement($oMenu, 'url')->GetAttribute('value');
+			$sUrl = $oMenu->GetChildText('url');
 			$sUrlSpec = $this->PathToPHP($sUrl, $sModuleRelativeDir, true /* Url */);
 			$sNewMenu = "new WebPageMenuNode('$sMenuId', $sUrlSpec, $sParentSpec, $fRank);";
 			break;
 
 		case 'TemplateMenuNode':
-			$sTemplateFile = $this->GetUniqueElement($oMenu, 'template_file')->GetAttribute('value');
+			$sTemplateFile = $oMenu->GetChildText('template_file');
 			$sTemplateSpec = $this->PathToPHP($sTemplateFile, $sModuleRelativeDir);
 			$sNewMenu = "new TemplateMenuNode('$sMenuId', $sTemplateSpec, $sParentSpec, $fRank);";
 			break;
 
 		case 'OQLMenuNode':
-			$sOQL = $this->GetUniqueElement($oMenu, 'oql')->GetAttribute('value');
-			$bSearch = ($this->GetUniqueElement($oMenu, 'do_search')->GetAttribute('value') == '1') ? 'true' : 'false';
+			$sOQL = $oMenu->GetChildText('oql');
+			$bSearch = ($oMenu->GetChildText('do_search') == '1') ? 'true' : 'false';
 			$sNewMenu = "new OQLMenuNode('$sMenuId', '$sOQL', $sParentSpec, $fRank, $bSearch);";
 			break;
 
 		case 'NewObjectMenuNode':
-			$sClass = $this->GetUniqueElement($oMenu, 'class')->GetAttribute('value');
+			$sClass = $oMenu->GetChildText('class');
 			$sNewMenu = "new NewObjectMenuNode('$sMenuId', '$sClass', $sParentSpec, $fRank);";
 			break;
 
 		case 'SearchMenuNode':
-			$sClass = $this->GetUniqueElement($oMenu, 'class')->GetAttribute('value');
+			$sClass = $oMenu->GetChildText('class');
 			$sNewMenu = "new SearchMenuNode('$sMenuId', '$sClass', $sParentSpec, $fRank);";
 			break;
 
 		case 'MenuGroup':
 		default:
-			if ($oEnableClass = $this->GetOptionalElement($oMenu, 'enable_class'))
+			if ($sEnableClass = $oMenu->GetChildText('enable_class'))
 			{
-				$sEnableClass = $oEnableClass->GetAttribute('value');
-				$sEnableAction = $this->GetUniqueElement($oMenu, 'enable_action')->GetAttribute('value');
-				$sEnablePermission = $this->GetUniqueElement($oMenu, 'enable_permission')->GetAttribute('value');
-				$sEnableStimulus = $this->GetUniqueElement($oMenu, 'enable_stimulus')->GetAttribute('value');
+				$sEnableAction = $oMenu->GetChildText('enable_action');
+				$sEnablePermission = $oMenu->GetChildText('enable_permission');
+				$sEnableStimulus = $oMenu->GetChildText('enable_stimulus');
 				if (strlen($sEnableStimulus) > 0)
 				{
 					$sNewMenu = "new MenuGroup('$sMenuId', $fRank, '$sEnableClass', $sEnableAction, $sEnablePermission, '$sEnableStimulus');";
@@ -884,14 +771,14 @@ EOF;
 
 		$sIndent = '';
 		$aPHPMenu = array("\$__comp_menus__['$sMenuId'] = $sNewMenu");
-		if ($oAutoReload = $this->GetOptionalElement($oMenu, 'auto_reload'))
+		if ($sAutoReload = $oMenu->GetChildText('auto_reload'))
 		{
-			$sAutoReload = addslashes($oAutoReload->GetAttribute("value"));
+			$sAutoReload = addslashes($sAutoReload);
 			$aPHPMenu[] = "\$__comp_menus__['$sMenuId']->SetParameters(array('auto_reload' => '$sAutoReload'));";
 		}
 
-		$oAdminOnly = $this->GetOptionalElement($oMenu, 'enable_admin_only');
-		if ($oAdminOnly && $oAdminOnly->GetAttribute('value') == '1')
+		$sAdminOnly = $oMenu->GetChildText('enable_admin_only');
+		if ($sAdminOnly && ($sAdminOnly == '1'))
 		{
 			$sPHP = $sIndent."if (UserRights::IsAdministrator())\n";
 			$sPHP .= $sIndent."{\n";

+ 122 - 72
setup/itop_design.xsd

@@ -15,12 +15,20 @@
           <xsd:complexType>
            <xsd:sequence>
             <xsd:element name="comment" type="xsd:string" minOccurs="0"/>
+            <xsd:element name="is_link" type="xsd:string" minOccurs="0"/>
+            <xsd:element name="category" type="xsd:string"/>
+            <xsd:element name="parent" type="xsd:string"/>
+            <xsd:element name="abstract" type="xsd:string"/>
+            <xsd:element name="key_type" type="xsd:string"/>
+            <xsd:element name="db_table" type="xsd:string"/>
+            <xsd:element name="db_key_field" type="xsd:string"/>
+            <xsd:element name="db_final_class_field" type="xsd:string"/>
             <xsd:element name="naming">
              <xsd:complexType>
               <xsd:sequence>
+               <xsd:element name="format" type="xsd:string"/>
                <xsd:element name="attributes" type="ListOfAttributes"/>
               </xsd:sequence>
-              <xsd:attribute name="format" type="xsd:string"/>
              </xsd:complexType>
             </xsd:element>
             <xsd:element name="display_template" type="xsd:string"/>
@@ -40,8 +48,11 @@
                  <xsd:sequence>
                   <xsd:element name="column">
                    <xsd:complexType>
-                    <xsd:attribute name="name" type="xsd:string"/>
-                    <xsd:attribute name="ascending" type="xsd:string"/>
+                    <xsd:sequence>
+                     <xsd:element name="ascending" type="xsd:string"/>
+                    </xsd:sequence>
+                    <xsd:attribute name="id" type="xsd:string" use="required"/>
+                    <xsd:attribute name="order" type="xsd:string" use="required"/>
                    </xsd:complexType>
                   </xsd:element>
                  </xsd:sequence>
@@ -64,15 +75,12 @@
           <xsd:complexType>
            <xsd:sequence>
 
+            <xsd:element name="attribute" type="xsd:string"/>
+
             <xsd:element name="stimuli">
              <xsd:complexType>
               <xsd:sequence>
-               <xsd:element name="stimulus" maxOccurs="unbounded">
-                <xsd:complexType>
-                 <xsd:attribute name="name" type="xsd:string"/>
-                 <xsd:attribute name="type" type="xsd:string"/>
-                </xsd:complexType>
-               </xsd:element>
+               <xsd:element name="stimulus" type="Stimulus" maxOccurs="unbounded"/>
               </xsd:sequence>
              </xsd:complexType>
             </xsd:element>
@@ -88,12 +96,14 @@
                     <xsd:sequence>
                      <xsd:element name="attribute" maxOccurs="unbounded">
                       <xsd:complexType>
-                       <xsd:attribute name="name" type="xsd:string"/>
-                       <xsd:attribute name="mandatory" type="xsd:string"/>
-                       <xsd:attribute name="must_prompt" type="xsd:string"/>
-                       <xsd:attribute name="must_change" type="xsd:string"/>
-                       <xsd:attribute name="hidden" type="xsd:string"/>
-                       <xsd:attribute name="read_only" type="xsd:string"/>
+                       <xsd:sequence>
+                        <xsd:element name="mandatory" type="xsd:string" minOccurs="0"/>
+                        <xsd:element name="must_prompt" type="xsd:string" minOccurs="0"/>
+                        <xsd:element name="must_change" type="xsd:string" minOccurs="0"/>
+                        <xsd:element name="hidden" type="xsd:string" minOccurs="0"/>
+                        <xsd:element name="read_only" type="xsd:string" minOccurs="0"/>
+                       </xsd:sequence>
+                       <xsd:attribute name="id" type="xsd:string" use="required"/>
                       </xsd:complexType>
                      </xsd:element>
                     </xsd:sequence>
@@ -106,27 +116,29 @@
                      <xsd:element name="transition" minOccurs="0" maxOccurs="unbounded">
                       <xsd:complexType>
                        <xsd:sequence>
+                       <xsd:element name="stimulus" type="xsd:string"/>
+                       <xsd:element name="target" type="xsd:string"/>
                         <xsd:element name="actions">
                          <xsd:complexType>
                           <xsd:sequence>
                            <xsd:element name="action" minOccurs="0" maxOccurs="unbounded">
                             <xsd:complexType>
-                             <xsd:attribute name="verb" type="xsd:string"/>
+                             <xsd:sequence>
+                              <xsd:element name="verb" type="xsd:string"/>
+                             </xsd:sequence>
                             </xsd:complexType>
                            </xsd:element>
                           </xsd:sequence>
                          </xsd:complexType>
                         </xsd:element>
                        </xsd:sequence>
-                       <xsd:attribute name="stimulus" type="xsd:string"/>
-                       <xsd:attribute name="target" type="xsd:string"/>
                       </xsd:complexType>
                      </xsd:element>
                     </xsd:sequence>
                    </xsd:complexType>
                   </xsd:element>
                  </xsd:sequence>
-                 <xsd:attribute name="name" type="xsd:string"/>
+                 <xsd:attribute name="id" type="xsd:string" use="required"/>
                 </xsd:complexType>
                </xsd:element>
               </xsd:sequence>
@@ -134,7 +146,6 @@
             </xsd:element>
 
            </xsd:sequence>
-           <xsd:attribute name="attribute" type="xsd:string"/>
           </xsd:complexType>
          </xsd:element>
          <xsd:element name="methods">
@@ -144,11 +155,12 @@
              <xsd:complexType mixed="true">
               <xsd:sequence>
                <xsd:element name="comment" type="xsd:string" minOccurs="0"/>
+               <xsd:element name="static" type="xsd:string"/>
+               <xsd:element name="access" type="xsd:string"/>
+               <xsd:element name="type" type="xsd:string"/>
+               <xsd:element name="code" type="xsd:string"/>
               </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string"/>
-              <xsd:attribute name="static" type="xsd:string"/>
-              <xsd:attribute name="access" type="xsd:string"/>
-              <xsd:attribute name="type" type="xsd:string"/>
+              <xsd:attribute name="id" type="xsd:string" use="required"/>
              </xsd:complexType>
             </xsd:element>
            </xsd:sequence>
@@ -164,15 +176,7 @@
           </xsd:complexType>
          </xsd:element>
         </xsd:sequence>
-        <xsd:attribute name="name" type="xsd:string"/>
-        <xsd:attribute name="category" type="xsd:string"/>
-        <xsd:attribute name="parent" type="xsd:string"/>
-        <xsd:attribute name="abstract" type="xsd:string"/>
-        <xsd:attribute name="key_type" type="xsd:string"/>
-        <xsd:attribute name="is_link" type="xsd:string"/>
-        <xsd:attribute name="db_table" type="xsd:string"/>
-        <xsd:attribute name="db_key_field" type="xsd:string"/>
-        <xsd:attribute name="db_final_class_field" type="xsd:string"/>
+        <xsd:attribute name="id" type="xsd:string" use="required"/>
        </xsd:complexType>
 
       </xsd:element>
@@ -195,7 +199,7 @@
 
 
 <!-- ====================================== -->
-<!-- Types for the classes                  -->
+<!-- Class: Atttributes                     -->
 <!-- ====================================== -->
 <xsd:complexType name="ListOfAttributes">
  <xsd:sequence>
@@ -206,23 +210,37 @@
 
 <xsd:complexType name="Attribute">
  <xsd:sequence>
+  <xsd:element name="filter" type="xsd:string" minOccurs="0"/>
+  <xsd:element name="values" minOccurs="0">
+   <xsd:complexType>
+    <xsd:sequence>
+     <xsd:element name="value" type="xsd:string" maxOccurs="unbounded"/>
+    </xsd:sequence>
+   </xsd:complexType>
+  </xsd:element>
   <xsd:element name="dependencies" type="ListOfAttributes" minOccurs="0"/>
  </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string"/>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
 </xsd:complexType>
 
 <xsd:complexType name="AttributeSql">
  <xsd:complexContent>
   <xsd:extension base="Attribute">
-   <xsd:attribute name="sql" type="xsd:string"/>
-   <xsd:attribute name="is_null_allowed" type="xsd:string"/>
+   <xsd:sequence>
+    <xsd:element name="sql" type="xsd:string"/>
+    <xsd:element name="default_value" type="xsd:string"/>
+    <xsd:element name="is_null_allowed" type="xsd:string"/>
+   </xsd:sequence>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
 
 <xsd:complexType name="AttributeBlob">
  <xsd:complexContent>
-  <xsd:extension base="AttributeSql">
+  <xsd:extension base="Attribute">
+   <xsd:sequence>
+    <xsd:element name="is_null_allowed" type="xsd:string" minOccurs="0"/>
+   </xsd:sequence>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
@@ -230,7 +248,8 @@
 <xsd:complexType name="AttributeScalar">
  <xsd:complexContent>
   <xsd:extension base="AttributeSql">
-   <xsd:attribute name="default_value" type="xsd:string"/>
+   <xsd:sequence>
+   </xsd:sequence>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
@@ -288,7 +307,9 @@
 <xsd:complexType name="AttributeURL">
  <xsd:complexContent>
   <xsd:extension base="AttributeString">
-   <xsd:attribute name="target" type="xsd:string"/>
+   <xsd:sequence>
+    <xsd:element name="target" type="xsd:string"/>
+   </xsd:sequence>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
@@ -303,25 +324,6 @@
 <xsd:complexType name="AttributeEnum">
  <xsd:complexContent>
   <xsd:extension base="AttributeString">
-   <xsd:sequence>
-    <xsd:element name="values">
-     <xsd:complexType>
-      <xsd:sequence>
-       <xsd:element name="value" type="xsd:string" maxOccurs="unbounded"/>
-      </xsd:sequence>
-     </xsd:complexType>
-    </xsd:element>
-   </xsd:sequence>
-  </xsd:extension>
- </xsd:complexContent>
-</xsd:complexType>
-
-
-<xsd:complexType name="AttributeExternalKeyBase">
- <xsd:complexContent>
-  <xsd:extension base="AttributeSql">
-   <xsd:attribute name="filter" type="xsd:string"/>
-   <xsd:attribute name="on_target_delete" type="xsd:string"/>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
@@ -329,25 +331,39 @@
 
 <xsd:complexType name="AttributeExternalKey">
  <xsd:complexContent>
-  <xsd:extension base="AttributeExternalKeyBase">
-   <xsd:attribute name="target_class" type="xsd:string"/>
-   <xsd:attribute name="jointype" type="xsd:string"/>
+  <xsd:extension base="Attribute">
+   <xsd:sequence>
+    <xsd:element name="sql" type="xsd:string"/>
+    <xsd:element name="target_class" type="xsd:string"/>
+    <xsd:element name="is_null_allowed" type="xsd:string"/>
+    <xsd:element name="filter" type="xsd:string" minOccurs="0"/>
+    <xsd:element name="on_target_delete" type="xsd:string"/>
+    <xsd:element name="jointype" type="xsd:string" minOccurs="0"/>
+   </xsd:sequence>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
 
 <xsd:complexType name="AttributeHierarchicalKey">
  <xsd:complexContent>
-  <xsd:extension base="AttributeExternalKeyBase">
+  <xsd:extension base="Attribute">
+   <xsd:sequence>
+    <xsd:element name="sql" type="xsd:string"/>
+    <xsd:element name="is_null_allowed" type="xsd:string"/>
+    <xsd:element name="on_target_delete" type="xsd:string"/>
+    <xsd:element name="filter" type="xsd:string" minOccurs="0"/>
+   </xsd:sequence>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
 
 <xsd:complexType name="AttributeExternalField">
  <xsd:complexContent>
-  <xsd:extension base="AttributeSql">
-   <xsd:attribute name="extkey_attcode" type="xsd:string"/>
-   <xsd:attribute name="target_attcode" type="xsd:string"/>
+  <xsd:extension base="Attribute">
+   <xsd:sequence>
+    <xsd:element name="extkey_attcode" type="xsd:string"/>
+    <xsd:element name="target_attcode" type="xsd:string"/>
+   </xsd:sequence>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
@@ -362,10 +378,12 @@
 <xsd:complexType name="AttributeLinkedSet">
  <xsd:complexContent>
   <xsd:extension base="Attribute">
-   <xsd:attribute name="linked_class" type="xsd:string"/>
-   <xsd:attribute name="ext_key_to_me" type="xsd:string"/>
-   <xsd:attribute name="count_min" type="xsd:integer"/>
-   <xsd:attribute name="count_max" type="xsd:integer"/>
+   <xsd:sequence>
+    <xsd:element name="linked_class" type="xsd:string"/>
+    <xsd:element name="ext_key_to_me" type="xsd:string"/>
+    <xsd:element name="count_min" type="xsd:string"/>
+    <xsd:element name="count_max" type="xsd:string"/>
+   </xsd:sequence>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
@@ -373,11 +391,18 @@
 <xsd:complexType name="AttributeLinkedSetIndirect">
  <xsd:complexContent>
   <xsd:extension base="AttributeLinkedSet">
+   <xsd:sequence>
+    <xsd:element name="ext_key_to_remote" type="xsd:string"/>
+   </xsd:sequence>
    <xsd:attribute name="ext_key_to_remote" type="xsd:string"/>
   </xsd:extension>
  </xsd:complexContent>
 </xsd:complexType>
 
+<!-- ====================================== -->
+<!-- Class: ZList (presentation)            -->
+<!-- ====================================== -->
+
 <xsd:complexType name="ItemList">
  <xsd:sequence>
   <xsd:element name="items" type="Items" minOccurs="0"/>
@@ -392,12 +417,34 @@
     <xsd:sequence>
      <xsd:element name="items" type="Items" minOccurs="0"/>
     </xsd:sequence>
-    <xsd:attribute name="key" type="xsd:string"/>
+    <xsd:attribute name="id" type="xsd:string"/>
    </xsd:complexType>
   </xsd:element>
  </xsd:sequence>
 </xsd:complexType>
 
+<!-- ====================================== -->
+<!-- Class: Stimulus                        -->
+<!-- ====================================== -->
+
+<xsd:complexType name="Stimulus">
+ <xsd:attribute name="id" type="xsd:string"/>
+</xsd:complexType>
+
+<xsd:complexType name="StimulusUserAction">
+ <xsd:complexContent>
+  <xsd:extension base="Stimulus">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="StimulusInternal">
+ <xsd:complexContent>
+  <xsd:extension base="Stimulus">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
 
 <!-- ====================================== -->
 <!-- Types for the menus                    -->
@@ -486,7 +533,10 @@
 </xsd:complexType>
 
 <xsd:complexType name="MenuProperty">
- <xsd:attribute name="value" type="xsd:string"/>
+ <xsd:simpleContent>
+  <xsd:extension base="xsd:string">
+  </xsd:extension>
+ </xsd:simpleContent>
 </xsd:complexType>
 
 <xsd:simpleType name="MenuType">

+ 86 - 67
setup/modelfactory.class.inc.php

@@ -284,6 +284,7 @@ class ModelFactory
 	{
 		$this->sRootDir = $sRootDir;
 		$this->oDOMDocument = new DOMDocument('1.0', 'UTF-8');
+		$this->oDOMDocument->registerNodeClass('DOMElement', 'MFDOMElement');
 		$this->oRoot = $this->oDOMDocument->CreateElement('itop_design');
 		$this->oDOMDocument->AppendChild($this->oRoot);
 		$this->oClasses = $this->oDOMDocument->CreateElement('classes');
@@ -319,6 +320,7 @@ class ModelFactory
 		foreach($aDataModels as $sXmlFile)
 		{
 			$oDocument = new DOMDocument('1.0', 'UTF-8');
+			$oDocument->registerNodeClass('DOMElement', 'MFDOMElement');
 			libxml_clear_errors();
 			$oDocument->load($sXmlFile, LIBXML_NOBLANKS);
 			$bValidated = $oDocument->schemaValidate(APPROOT.'setup/itop_design.xsd');
@@ -326,6 +328,7 @@ class ModelFactory
 			if (count($aErrors) > 0)
 			{
 				self::$aLoadErrors[$sModuleName] = $aErrors;
+				return;
 			}
 
 			$oXPath = new DOMXPath($oDocument);
@@ -338,15 +341,8 @@ class ModelFactory
 			$oNodeList = $oXPath->query('/itop_design/classes/class');
 			foreach($oNodeList as $oNode)
 			{
-				if ($oNode->hasAttribute('parent'))
-				{
-					$sParentClass = $oNode->GetAttribute('parent');
-				}
-				else
-				{
-					$sParentClass = '';
-				}
-				$sClassName = $oNode->GetAttribute('name');
+				$sParentClass = $oNode->GetUniqueElement('properties')->GetChildText('parent', '');
+				$sClassName = $oNode->GetAttribute('id');
 				$aClasses[$sClassName] = array('name' => $sClassName, 'parent' => $sParentClass, 'node' => $oNode);
 			}
 
@@ -474,9 +470,9 @@ class ModelFactory
 	 */
 	protected function ClassExists(DOMNode $oClassNode)
 	{
-		if ($oClassNode->hasAttribute('name'))
+		if ($oClassNode->hasAttribute('id'))
 		{
-			$sClassName = $oClassNode->GetAttribute('name');
+			$sClassName = $oClassNode->GetAttribute('id');
 		}
 		else
 		{
@@ -504,9 +500,9 @@ class ModelFactory
 	 */
 	public function AddClass(DOMNode $oClassNode, $sModuleName)
 	{
-		if ($oClassNode->hasAttribute('name'))
+		if ($oClassNode->hasAttribute('id'))
 		{
-			$sClassName = $oClassNode->GetAttribute('name');
+			$sClassName = $oClassNode->GetAttribute('id');
 		}
 		else
 		{
@@ -517,11 +513,7 @@ class ModelFactory
 			throw new Exception("ModelFactory::AddClass: Cannot add the already existing class $sClassName");
 		}
 		
-		$sParentClass = '';
-		if ($oClassNode->hasAttribute('parent'))
-		{
-			$sParentClass = $oClassNode->GetAttribute('parent');
-		}
+		$sParentClass = $oClassNode->GetUniqueElement('properties')->GetChildText('parent', '');
 		
 		//echo "Adding class: $sClassName, parent: $sParentClass<br/>";
 		if (!in_array($sParentClass, self::$aWellKnownParents) && $this->ClassNameExists($sParentClass))
@@ -549,7 +541,7 @@ class ModelFactory
 		}
 		else
 		{
-			throw new Exception("ModelFactory::AddClass: Cannot add the class $sClassName, unknown parent class: $sParentClass");
+			throw new Exception("ModelFactory::AddClass: Cannot add the class $sClassName, unknown parent class: $sParentClass (loaded classes: ".implode(', ', array_keys(self::$aLoadedClasses)).")");
 		}
 	}
 	
@@ -605,7 +597,7 @@ class ModelFactory
 			}
 		}
 		$this->_priv_AlterNode($oDestNode, $oClassNode);
-		$sClassName = $oDestNode->getAttribute('name');
+		$sClassName = $oDestNode->getAttribute('id');
 		if ($sOriginalName != $sClassName)
 		{
 			unset(self::$aLoadedClasses[$sOriginalName]);
@@ -711,10 +703,10 @@ class ModelFactory
 			{
 				$sOperation = $oChildNode->getAttribute('_operation');
 				$sPath = $oChildNode->tagName;
-				$sName = $oChildNode->getAttribute('name');
+				$sName = $oChildNode->getAttribute('id');
 				if ($sName != '')
 				{
-					$sPath .= "[@name='$sName']";
+					$sPath .= "[@id='$sName']";
 				}
 				switch($sOperation)
 				{
@@ -762,15 +754,17 @@ class ModelFactory
 		return
 <<<EOF
 <?xml version="1.0" encoding="utf-8"?>
-<class name="$sName" parent="" db_table="" category="" abstract="" key_type="autoincrement" db_key_field="id" db_final_class_field="finalclass">
-	<properties>
+<class id="$sName">
 	<comment/>
+	<properties>
+	</properties>
 	<naming format=""><attributes/></naming>
 	<reconciliation><attributes/></reconciliation>
 	<display_template/>
 	<icon>$sIcon</icon>
 	</properties>
 	<fields/>
+	<lifecycle/>
 	<methods/>
 	<presentation>
 		<details><items/></details>
@@ -857,15 +851,15 @@ EOF
 				$oClassNode = null;
 			}
 		}
-		$sXPath = "fields/field[@name='$sAttCode']";
+		$sXPath = "fields/field[@id='$sAttCode']";
 		if ($bFlattenLayers)
 		{
-			$sXPath = "fields/field[(@name='$sAttCode' and (not(@_operation) or @_operation!='removed'))]";
+			$sXPath = "fields/field[(@id='$sAttCode' and (not(@_operation) or @_operation!='removed'))]";
 		}
 		$oFieldNode = $this->_priv_GetNodes($sXPath, $oClassNode)->item(0);
-		if (($oFieldNode == null) && ($oClassNode->getAttribute('parent') != ''))
+		if (($oFieldNode == null) && ($sParentClass = $oClassNode->GetUniqueElement('properties')->GetChildText('parent')))
 		{
-			return $this->GetField($oClassNode->getAttribute('parent'), $sAttCode, $bFlattenLayers);
+			return $this->GetField($sParentClass, $sAttCode, $bFlattenLayers);
 		}
 		return $oFieldNode;
 	}
@@ -888,7 +882,7 @@ EOF
 	public function AddField(DOMNode $oClassNode, $sFieldCode, $sFieldType, $sSQL, $defaultValue, $bIsNullAllowed, $aExtraParams)
 	{
 		$oNewField = $this->oDOMDocument->createElement('field');
-		$oNewField->setAttribute('name', $sFieldCode);
+		$oNewField->setAttribute('id', $sFieldCode);
 		$this->_priv_AlterField($oNewField, $sFieldType, $sSQL, $defaultValue, $bIsNullAllowed, $aExtraParams);
 		$oFields = $oClassNode->getElementsByTagName('fields')->item(0);
 		$oFields->AppendChild($oNewField);
@@ -897,7 +891,7 @@ EOF
 	
 	public function RemoveField(DOMNode $oClassNode, $sFieldCode)
 	{
-		$sXPath = "fields/field[@name='$sFieldCode']";
+		$sXPath = "fields/field[@id='$sFieldCode']";
 		$oFieldNodes = $this->_priv_GetNodes($sXPath, $oClassNode);
 		if (is_object($oFieldNodes) && (is_object($oFieldNodes->item(0))))
 		{
@@ -916,7 +910,7 @@ EOF
 	
 	public function AlterField(DOMNode $oClassNode, $sFieldCode, $sFieldType, $sSQL, $defaultValue, $bIsNullAllowed, $aExtraParams)
 	{
-		$sXPath = "fields/field[@name='$sFieldCode']";
+		$sXPath = "fields/field[@id='$sFieldCode']";
 		$oFieldNodes = $this->_priv_GetNodes($sXPath, $oClassNode);
 		if (is_object($oFieldNodes) && (is_object($oFieldNodes->item(0))))
 		{
@@ -1031,7 +1025,7 @@ EOF
 		foreach($aDeps as $sAttCode)
 		{
 			$oDep = $this->oDOMDocument->createElement('attribute');
-			$oDep->setAttribute('name', $sAttCode);
+			$oDep->setAttribute('id', $sAttCode);
 			$oDependencies->addChild($oDep);
 		}
 		$oFieldNode->addChild($oDependencies);
@@ -1225,7 +1219,7 @@ EOF
 				case 'removed':
 				// marked as deleted, let's remove the node from the tree
 				$oParent = $oClassNode->parentNode;
-				$sClass = $oClassNode->GetAttribute('name');
+				$sClass = $oClassNode->GetAttribute('id');
 				echo "Calling removeChild...<br/>";
 				$oParent->removeChild($oClassNode);
 				unset(self::$aLoadedClasses[$sClass]);
@@ -1246,6 +1240,7 @@ EOF
 	public function GetDelta()
 	{
 		$oDelta = new DOMDocument('1.0', 'UTF-8');
+		$oDelta->registerNodeClass('DOMElement', 'MFDOMElement');
 		$oRootNode = $oDelta->createElement('itop_design');
 		$oDelta->appendChild($oRootNode);
 		$oClasses = $oDelta->createElement('classes');
@@ -1272,7 +1267,7 @@ EOF
 			}
 			else
 			{
-				$sName = $oChildNode->getAttribute('name');;
+				$sName = $oChildNode->getAttribute('id');;
 				$sOperation = $oChildNode->getAttribute('_operation');
 			}
 			
@@ -1292,18 +1287,18 @@ echo str_repeat('+', $iDepth)." $sNodeName [$sName], operation: $sOperation\n";
 				{
 					$oDestNode->appendChild($oDeletedNode);
 				}
-echo "<p>".str_repeat('+', $iDepth).$oChildNode->getAttribute('name')." was removed...</p>";
+echo "<p>".str_repeat('+', $iDepth).$oChildNode->getAttribute('id')." was removed...</p>";
 				break;
 
 				case 'added':
-echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." was created...</p>";
+echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('id')." was created...</p>";
 				$oModifiedNode = $oDoc->importNode($oChildNode, true); // Copies all the node's attributes, and the child nodes as well
 				if ($oChildNode instanceof DOMElement)
 				{
 					$oModifiedNode->removeAttribute('_source');
 					if ($oModifiedNode->tagName == 'class')
 					{
-echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." inserting under 'classes'...</p>";
+echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('id')." inserting under 'classes'...</p>";
 						// classes are always located under the root node
 						$oDoc->firstChild->appendChild($oModifiedNode);
 						
@@ -1322,7 +1317,7 @@ echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAtt
 					}
 					else
 					{
-echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." inserting in the hierarchy...</p>";
+echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('id')." inserting in the hierarchy...</p>";
 						$oDestNode->appendChild($oModifiedNode);
 					}
 				}
@@ -1333,7 +1328,7 @@ echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAtt
 				break;
 				
 				case 'replaced':
-echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." was replaced...</p>";
+echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('id')." was replaced...</p>";
 				$oModifiedNode = $oDoc->importNode($oChildNode, true); // Copies all the node's attributes, and the child nodes as well
 				if ($oChildNode instanceof DOMElement)
 				{
@@ -1343,7 +1338,7 @@ echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAtt
 				break;
 				
 				case 'modified':
-echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." was modified...</p>";
+echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('id')." was modified...</p>";
 				if ($oChildNode instanceof DOMElement)
 				{
 echo str_repeat('+', $iDepth)." Copying (NON recursively) the modified node\n";
@@ -1370,11 +1365,11 @@ echo str_repeat('+', $iDepth)." Copying (recursively) the modified node\n";
 				
 				default:
 				// No change: do nothing
-echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('name')." was NOT modified...</p>";
+echo "<p>".str_repeat('+', $iDepth).$oChildNode->tagName.':'.$oChildNode->getAttribute('id')." was NOT modified...</p>";
 				$oModifiedNode = $oDoc->importNode($oChildNode, true); // Importing the node for future recusrsion if needed
 				if ($oChildNode->tagName == 'class')
 				{
-echo "<p>".str_repeat('+', $iDepth)."Checking if a subclass of ".$oChildNode->getAttribute('name')." was modified...</p>";
+echo "<p>".str_repeat('+', $iDepth)."Checking if a subclass of ".$oChildNode->getAttribute('id')." was modified...</p>";
 					// classes are always located under the root node
 					$this->_priv_ImportModifiedChildren($oDoc, $oModifiedNode, $oChildNode);
 				}
@@ -1454,15 +1449,22 @@ echo "<p>".str_repeat('+', $iDepth)."Checking if a subclass of ".$oChildNode->ge
 	public function _priv_SetNodeAttribute(DOMNode $oNode, $sAttributeName, $atttribueValue)
 	{
 	}
-	
+}
+
+
+/**
+ * MFDOMElement: helper to read the information from the DOM
+ * @package ModelFactory
+ */
+class MFDOMElement extends DOMElement
+{
 	/**
-	 * Helper to browse the DOM -could be factorized in ModelFactory
-	 * Returns the node directly under the given node, and that is supposed to be always present and unique 
+	 * Returns the node directly under the given node 
 	 */ 
-	protected function GetUniqueElement($oDOMNode, $sTagName, $bMustExist = true)
+	public function GetUniqueElement($sTagName, $bMustExist = true)
 	{
 		$oNode = null;
-		foreach($oDOMNode->childNodes as $oChildNode)
+		foreach($this->childNodes as $oChildNode)
 		{
 			if ($oChildNode->nodeName == $sTagName)
 			{
@@ -1478,35 +1480,53 @@ echo "<p>".str_repeat('+', $iDepth)."Checking if a subclass of ".$oChildNode->ge
 	}
 	
 	/**
-	 * Helper to browse the DOM -could be factorized in ModelFactory
-	 * Returns the node directly under the given node, or null is missing 
+	 * Returns the node directly under the current node, or null if missing 
 	 */ 
-	protected function GetOptionalElement($oDOMNode, $sTagName)
+	public function GetOptionalElement($sTagName)
 	{
-		return $this->GetUniqueElement($oDOMNode, $sTagName, false);
+		return $this->GetUniqueElement($sTagName, false);
 	}
 	
 	
 	/**
-	 * Helper to browse the DOM -could be factorized in ModelFactory
-	 * Returns the TEXT of the given node (possibly from several subnodes) 
+	 * Returns the TEXT of the current node (possibly from several subnodes) 
 	 */ 
-	protected function GetNodeText($oNode)
+	public function GetText($sDefault = null)
 	{
-		$sText = '';
-		foreach($oNode->childNodes as $oChildNode)
+		$sText = null;
+		foreach($this->childNodes as $oChildNode)
 		{
 			if ($oChildNode instanceof DOMCharacterData) // Base class of DOMText and DOMCdataSection
 			{
+				if (is_null($sText)) $sText = '';
 				$sText .= $oChildNode->wholeText;
 			}
 		}
-		return $sText;
+		if (is_null($sText))
+		{
+			return $sDefault;
+		}
+		else
+		{
+			return $sText;
+		}
 	}
 	
 	/**
-	 * Helper to browse the DOM -could be factorized in ModelFactory
-	 * Assumes the given node to be either a text or
+	 * Get the TEXT value from the child node 
+	 */ 
+	public function GetChildText($sTagName, $sDefault = null)
+	{
+		$sRet = $sDefault;
+		if ($oChild = $this->GetOptionalElement($sTagName))
+		{
+			$sRet = $oChild->GetText($sDefault);
+		}
+		return $sRet;
+	}
+
+	/**
+	 * Assumes the current node to be either a text or
 	 * <items>
 	 *   <item [key]="..."]>value<item>
 	 *   <item [key]="..."]>value<item>
@@ -1514,31 +1534,30 @@ echo "<p>".str_repeat('+', $iDepth)."Checking if a subclass of ".$oChildNode->ge
 	 * where value can be the either a text or an array of items... recursively 
 	 * Returns a PHP array 
 	 */ 
-	public function GetNodeAsArrayOfItems($oNode)
+	public function GetNodeAsArrayOfItems()
 	{
-		$oItems = $this->GetOptionalElement($oNode, 'items');
+		$oItems = $this->GetOptionalElement('items');
 		if ($oItems)
 		{
 			$res = array();
 			foreach($oItems->childNodes as $oItem)
 			{
 				// When an attribute is missing
-				if ($oItem->hasAttribute('key'))
+				if ($oItem->hasAttribute('id'))
 				{
-					$key = $oItem->getAttribute('key');
-					$res[$key] = $this->GetNodeAsArrayOfItems($oItem);
+					$key = $oItem->getAttribute('id');
+					$res[$key] = $oItem->GetNodeAsArrayOfItems();
 				}
 				else
 				{
-					$res[] = $this->GetNodeAsArrayOfItems($oItem);
+					$res[] = $oItem->GetNodeAsArrayOfItems();
 				}
 			}
 		}
 		else
 		{
-			$res = $this->GetNodeText($oNode);
+			$res = $this->GetText();
 		}
 		return $res;
 	}
-	
 }

Деякі файли не було показано, через те що забагато файлів було змінено