Browse Source

Compiler: clearer reporting on XML format issues + additional validation by the mean of an XSD (same reporting chanel). The validation provided by the XSD is not strict, but this is a good starting point.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1952 a333f486-631f-4898-b8df-5754b55c2be0
romainq 13 years ago
parent
commit
afd07bb20f
2 changed files with 527 additions and 2 deletions
  1. 501 0
      setup/itop_design.xsd
  2. 26 2
      setup/modelfactory.class.inc.php

+ 501 - 0
setup/itop_design.xsd

@@ -0,0 +1,501 @@
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+<xsd:element name="itop_design">
+ <xsd:complexType>
+  <xsd:sequence>
+
+   <!-- Classes [0, N] -->
+   <xsd:element name="classes" minOccurs="0">
+    <xsd:complexType>
+     <xsd:sequence>
+      <xsd:element name="class" minOccurs="0" maxOccurs="unbounded">
+       <xsd:complexType>
+        <xsd:sequence>
+         <xsd:element name="properties">
+          <xsd:complexType>
+           <xsd:sequence>
+            <xsd:element name="comment" type="xsd:string" minOccurs="0"/>
+            <xsd:element name="naming">
+             <xsd:complexType>
+              <xsd:sequence>
+               <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"/>
+            <xsd:element name="icon" type="xsd:string"/>
+            <xsd:element name="reconciliation">
+             <xsd:complexType>
+              <xsd:sequence>
+               <xsd:element name="attributes" type="ListOfAttributes"/>
+              </xsd:sequence>
+             </xsd:complexType>
+            </xsd:element>
+            <xsd:element name="order" minOccurs="0">
+             <xsd:complexType>
+              <xsd:sequence>
+               <xsd:element name="columns">
+                <xsd:complexType>
+                 <xsd:sequence>
+                  <xsd:element name="column">
+                   <xsd:complexType>
+                    <xsd:attribute name="name" type="xsd:string"/>
+                    <xsd:attribute name="ascending" type="xsd:string"/>
+                   </xsd:complexType>
+                  </xsd:element>
+                 </xsd:sequence>
+                </xsd:complexType>
+               </xsd:element>
+              </xsd:sequence>
+             </xsd:complexType>
+            </xsd:element>
+           </xsd:sequence>
+          </xsd:complexType>
+         </xsd:element>
+         <xsd:element name="fields">
+          <xsd:complexType>
+           <xsd:sequence>
+            <xsd:element name="field" type="Attribute" minOccurs="0" maxOccurs="unbounded"/>
+           </xsd:sequence>
+          </xsd:complexType>
+         </xsd:element>
+         <xsd:element name="lifecycle" minOccurs="0">
+          <xsd:complexType>
+           <xsd:sequence>
+
+            <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:sequence>
+             </xsd:complexType>
+            </xsd:element>
+
+            <xsd:element name="states">
+             <xsd:complexType>
+              <xsd:sequence>
+               <xsd:element name="state" minOccurs="0" maxOccurs="unbounded">
+                <xsd:complexType>
+                 <xsd:sequence>
+                  <xsd:element name="flags">
+                   <xsd:complexType>
+                    <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:complexType>
+                     </xsd:element>
+                    </xsd:sequence>
+                   </xsd:complexType>
+                  </xsd:element>
+                  
+                  <xsd:element name="transitions">
+                   <xsd:complexType>
+                    <xsd:sequence>
+                     <xsd:element name="transition" minOccurs="0" maxOccurs="unbounded">
+                      <xsd:complexType>
+                       <xsd:sequence>
+                        <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: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:complexType>
+               </xsd:element>
+              </xsd:sequence>
+             </xsd:complexType>
+            </xsd:element>
+
+           </xsd:sequence>
+           <xsd:attribute name="attribute" type="xsd:string"/>
+          </xsd:complexType>
+         </xsd:element>
+         <xsd:element name="methods">
+          <xsd:complexType>
+           <xsd:sequence>
+            <xsd:element name="method" minOccurs="0" maxOccurs="unbounded">
+             <xsd:complexType mixed="true">
+              <xsd:sequence>
+               <xsd:element name="comment" type="xsd:string" minOccurs="0"/>
+              </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:complexType>
+            </xsd:element>
+           </xsd:sequence>
+          </xsd:complexType>
+         </xsd:element>
+         <xsd:element name="presentation">
+          <xsd:complexType>
+           <xsd:all>
+            <xsd:element name="details" type="ItemList" minOccurs="0"/>
+            <xsd:element name="search" type="ItemList" minOccurs="0"/>
+            <xsd:element name="list" type="ItemList" minOccurs="0"/>
+           </xsd:all>
+          </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:complexType>
+
+      </xsd:element>
+     </xsd:sequence>
+    </xsd:complexType>
+   </xsd:element>
+
+   <!-- Menus [0, N] -->
+   <xsd:element name="menus" minOccurs="0">
+    <xsd:complexType>
+     <xsd:sequence>
+      <xsd:element name="menu" type="Menu" minOccurs="0" maxOccurs="unbounded"/>
+     </xsd:sequence>
+    </xsd:complexType>
+   </xsd:element>
+   
+  </xsd:sequence>
+ </xsd:complexType>
+</xsd:element>
+
+
+<!-- ====================================== -->
+<!-- Types for the classes                  -->
+<!-- ====================================== -->
+<xsd:complexType name="ListOfAttributes">
+ <xsd:sequence>
+  <xsd:element name="attribute" minOccurs="0" maxOccurs="unbounded">
+  </xsd:element>
+ </xsd:sequence>
+</xsd:complexType>
+
+<xsd:complexType name="Attribute">
+ <xsd:sequence>
+  <xsd:element name="dependencies" type="ListOfAttributes" minOccurs="0"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string"/>
+</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:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeBlob">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeSql">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeScalar">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeSql">
+   <xsd:attribute name="default_value" type="xsd:string"/>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeInteger">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeScalar">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeString">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeScalar">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeDate">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeString">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeDateTime">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeString">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeDeadline">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeDateTime">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+
+<xsd:complexType name="AttributeText">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeString">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeCaseLog">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeText">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeURL">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeString">
+   <xsd:attribute name="target" type="xsd:string"/>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeIPAddress">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeString">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<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>
+
+
+<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>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeHierarchicalKey">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeExternalKeyBase">
+  </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>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeEmailAddress">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeString">
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<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:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="AttributeLinkedSetIndirect">
+ <xsd:complexContent>
+  <xsd:extension base="AttributeLinkedSet">
+   <xsd:attribute name="ext_key_to_remote" type="xsd:string"/>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="ItemList">
+ <xsd:sequence>
+  <xsd:element name="items" type="Items" minOccurs="0"/>
+ </xsd:sequence>
+</xsd:complexType>
+
+
+<xsd:complexType name="Items">
+ <xsd:sequence>
+  <xsd:element name="item" maxOccurs="unbounded">
+   <xsd:complexType mixed="true">
+    <xsd:sequence>
+     <xsd:element name="items" type="Items" minOccurs="0"/>
+    </xsd:sequence>
+    <xsd:attribute name="key" type="xsd:string"/>
+   </xsd:complexType>
+  </xsd:element>
+ </xsd:sequence>
+</xsd:complexType>
+
+
+<!-- ====================================== -->
+<!-- Types for the menus                    -->
+<!-- ====================================== -->
+<xsd:complexType name="Menu">
+ <xsd:sequence>
+  <xsd:element name="rank" type="MenuProperty"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string"/>
+</xsd:complexType>
+
+<xsd:complexType name="MenuGroup">
+ <xsd:complexContent>
+  <xsd:extension base="Menu">
+   <xsd:sequence>
+    <xsd:element name="enable_class" type="MenuProperty" minOccurs="0"/>
+    <xsd:element name="enable_action" type="MenuProperty" minOccurs="0"/>
+    <xsd:element name="enable_permission" type="MenuProperty" minOccurs="0"/>
+    <xsd:element name="enable_stimulus" type="MenuProperty" minOccurs="0"/>
+   </xsd:sequence>
+   <xsd:attribute name="type" type="xsd:string" fixed="MenuGroup"/>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="MenuNode">
+ <xsd:complexContent>
+  <xsd:extension base="Menu">
+   <xsd:sequence>
+    <xsd:element name="parent" type="MenuProperty"/>
+   </xsd:sequence>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="TemplateMenuNode">
+ <xsd:complexContent>
+  <xsd:extension base="MenuNode">
+   <xsd:sequence>
+    <xsd:element name="template_file" type="MenuProperty"/>
+   </xsd:sequence>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="NewObjectMenuNode">
+ <xsd:complexContent>
+  <xsd:extension base="MenuNode">
+   <xsd:sequence>
+    <xsd:element name="class" type="MenuProperty"/>
+   </xsd:sequence>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="SearchMenuNode">
+ <xsd:complexContent>
+  <xsd:extension base="MenuNode">
+   <xsd:sequence>
+    <xsd:element name="class" type="MenuProperty"/>
+   </xsd:sequence>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="OQLMenuNode">
+ <xsd:complexContent>
+  <xsd:extension base="MenuNode">
+   <xsd:sequence>
+    <xsd:element name="oql" type="MenuProperty"/>
+    <xsd:element name="do_search" type="MenuProperty"/>
+    <xsd:element name="auto_reload" type="MenuProperty" minOccurs="0"/>
+   </xsd:sequence>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="WebPageMenuNode">
+ <xsd:complexContent>
+  <xsd:extension base="MenuNode">
+   <xsd:sequence>
+    <xsd:element name="url" type="MenuProperty"/>
+   </xsd:sequence>
+  </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="MenuProperty">
+ <xsd:attribute name="value" type="xsd:string"/>
+</xsd:complexType>
+
+<xsd:simpleType name="MenuType">
+  <xsd:restriction base="xsd:string">
+    <xsd:enumeration value="MenuGroup"/>
+    <xsd:enumeration value="TemplateMenuNode"/>
+    <xsd:enumeration value="NewObjectMenuNode"/>
+    <xsd:enumeration value="SearchMenuNode"/>
+    <xsd:enumeration value="OQLMenuNode"/>
+  </xsd:restriction>
+</xsd:simpleType>
+</xsd:schema>

+ 26 - 2
setup/modelfactory.class.inc.php

@@ -277,7 +277,8 @@ class ModelFactory
 	static protected $aLoadedMenus;
 	static protected $aWellKnownParents = array('DBObject', 'CMDBObject','cmdbAbstractObject');
 	static protected $aLoadedModules;
-	
+	static protected $aLoadErrors;
+
 	
 	public function __construct($sRootDir)
 	{
@@ -292,6 +293,9 @@ class ModelFactory
 		self::$aLoadedClasses = array();
 		self::$aLoadedMenus = array();
 		self::$aLoadedModules = array();
+		self::$aLoadErrors = array();
+
+		libxml_use_internal_errors(true);
 	}
 	
 	public function Dump($oNode = null)
@@ -315,7 +319,15 @@ class ModelFactory
 		foreach($aDataModels as $sXmlFile)
 		{
 			$oDocument = new DOMDocument('1.0', 'UTF-8');
+			libxml_clear_errors();
 			$oDocument->load($sXmlFile, LIBXML_NOBLANKS);
+			$bValidated = $oDocument->schemaValidate(APPROOT.'setup/itop_design.xsd');
+			$aErrors = libxml_get_errors();
+			if (count($aErrors) > 0)
+			{
+				self::$aLoadErrors[$sModuleName] = $aErrors;
+			}
+
 			$oXPath = new DOMXPath($oDocument);
 			$oNodeList = $oXPath->query('//*');
 			foreach($oNodeList as $oNode)
@@ -410,7 +422,19 @@ class ModelFactory
 			}
 		}			
 	}
-	
+
+	/**
+	 *	XML load errors (XML format and validation)
+	 */	
+	function HasLoadErrors()
+	{
+		return (count(self::$aLoadErrors) > 0);
+	}
+	function GetLoadErrors()
+	{
+		return self::$aLoadErrors;
+	}
+
 	function GetLoadedModules($bExcludeWorkspace = true)
 	{
 		if ($bExcludeWorkspace)