瀏覽代碼

New concept in the XML: HighlightScale to avoid overloading GetIcon and GetHilightClass...

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@3291 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 11 年之前
父節點
當前提交
2f3a180cb0

+ 1 - 1
application/cmdbabstract.class.inc.php

@@ -2460,7 +2460,7 @@ EOF
 	{
 		// Possible return values are:
 		// HILIGHT_CLASS_CRITICAL, HILIGHT_CLASS_WARNING, HILIGHT_CLASS_OK, HILIGHT_CLASS_NONE	
-		$current = HILIGHT_CLASS_NONE; // Not hilighted by default
+		$current = parent::GetHilightClass(); // Default computation
 
 		// Invoke extensions before the deletion (the deletion will do some cleanup and we might loose some information
 		foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)

+ 3 - 2
core/attributedef.class.inc.php

@@ -3717,7 +3717,7 @@ class AttributeStopWatch extends AttributeDefinition
 		);
 
 		$aThresholds = array();
-		foreach ($this->ListThresholds() as $iThreshold => $aFoo)
+		foreach ($this->ListThresholds() as $iThreshold => $aDefinition)
 		{
 			$sThPrefix = '_'.$iThreshold;
 			$value->DefineThreshold(
@@ -3725,7 +3725,8 @@ class AttributeStopWatch extends AttributeDefinition
 				self::DateToSeconds($aCols[$sPrefix.$sThPrefix.'_deadline']),
 				(bool)($aCols[$sPrefix.$sThPrefix.'_passed'] == 1),
 				(bool)($aCols[$sPrefix.$sThPrefix.'_triggered'] == 1),
-				$aCols[$sPrefix.$sThPrefix.'_overrun']
+				$aCols[$sPrefix.$sThPrefix.'_overrun'],
+				array_key_exists('highlight', $aDefinition) ? $aDefinition['highlight'] : null
 			);
 		}
 

+ 132 - 9
core/dbobject.class.php

@@ -95,6 +95,7 @@ abstract class DBObject implements iDisplay
 	private $m_aLoadedAtt = array(); // Compound objects can be partially loaded, array of sAttCode
 	protected $m_aModifiedAtt = array(); // list of (potentially) modified sAttCodes
 	protected $m_oMasterReplicaSet = null; // Set of SynchroReplica related to this object
+	protected $m_sHighlightCode = null;
 
 	// Use the MetaModel::NewObject to build an object (do we have to force it?)
 	public function __construct($aRow = null, $sClassAlias = '', $aAttToLoad = null, $aExtendedDataSpec = null)
@@ -557,6 +558,64 @@ abstract class DBObject implements iDisplay
 	{
 		return $this->m_aExtendedData;
 	}
+	
+	/**
+	 * Set the HighlightCode if the given code has a greater rank than the current HilightCode
+	 * @param string $sCode
+	 * @return void
+	 */
+	protected function SetHighlightCode($sCode)
+	{
+		$aHighlightScale = MetaModel::GetHighlightScale(get_class($this));
+		$fCurrentRank = 0.0;
+		if (($this->m_sHighlightCode !== null) && array_key_exists($this->m_sHighlightCode, $aHighlightScale))
+		{
+			$fCurrentRank = $aHighlightScale[$this->m_sHighlightCode]['rank'];
+		}
+				
+		if (array_key_exists($sCode, $aHighlightScale))
+		{
+			$fRank = $aHighlightScale[$sCode]['rank'];
+			if ($fRank > $fCurrentRank)
+			{
+				$this->m_sHighlightCode = $sCode;
+			}
+		}
+	}
+	
+	/**
+	 * Get the current HighlightCode
+	 * @return string The Hightlight code (null if none set, meaning rank = 0)
+	 */
+	protected function GetHighlightCode()
+	{
+		return $this->m_sHighlightCode;
+	}
+	
+	protected function ComputeHighlightCode()
+	{
+		// First if the state defines a HiglightCode, apply it
+		$sState = $this->GetState();
+		if ($sState != '')
+		{
+			$sCode = MetaModel::GetHighlightCode(get_class($this), $sState);
+			$this->SetHighlightCode($sCode);
+		}
+		// The check for each StopWatch if a HighlightCode is effective
+		foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef)
+		{
+			if ($oAttDef instanceof AttributeStopWatch)
+			{
+				$oStopWatch = $this->Get($sAttCode);
+				$sCode = $oStopWatch->GetHighlightCode();
+				if ($sCode !== '')
+				{
+					$this->SetHighlightCode($sCode);
+				}
+			}
+		}
+		return $this->GetHighlightCode();
+	}
 
 	/**
 	 * Updates the value of an external field by (re)loading the object
@@ -785,10 +844,27 @@ abstract class DBObject implements iDisplay
 	/**
 	 * Get the icon representing this object
 	 * @param boolean $bImgTag If true the result is a full IMG tag (or an emtpy string if no icon is defined)
-	 * @return string Either the full IMG tag ($bImgTag == true) or just the path to the icon file
+	 * @return string Either the full IMG tag ($bImgTag == true) or just the URL to the icon file
 	 */
 	public function GetIcon($bImgTag = true)
 	{
+		$sCode = $this->ComputeHighlightCode();
+		if($sCode != '')
+		{
+			$aHighlightScale = MetaModel::GetHighlightScale(get_class($this));
+			if (array_key_exists($sCode, $aHighlightScale))
+			{
+				$sIconUrl = $aHighlightScale[$sCode]['icon'];
+				if($bImgTag)
+				{
+					return "<img src=\"$sIconUrl\" style=\"vertical-align:middle\"/>";
+				}
+				else
+				{
+					return $sIconUrl;
+				}
+			}
+		}		
 		return MetaModel::GetClassIcon(get_class($this), $bImgTag);
 	}
 
@@ -1998,17 +2074,55 @@ abstract class DBObject implements iDisplay
 		//    array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD
 
 		$bSuccess = true;
-		foreach ($aTransitionDef['actions'] as $sActionHandler)
+		foreach ($aTransitionDef['actions'] as $actionHandler)
 		{
-			// std PHP spec
-			$aActionCallSpec = array($this, $sActionHandler);
-
-			if (!is_callable($aActionCallSpec))
+			if (is_string($actionHandler))
 			{
-				throw new CoreException("Unable to call action: ".get_class($this)."::$sActionHandler");
-				return;
+				// Old (pre-2.0.4) action definition without any parameter
+				$aActionCallSpec = array($this, $sActionHandler);
+	
+				if (!is_callable($aActionCallSpec))
+				{
+					throw new CoreException("Unable to call action: ".get_class($this)."::$sActionHandler");
+					return;
+				}
+				$bRet = call_user_func($aActionCallSpec, $sStimulusCode);
+			}
+			else // if (is_array($actionHandler))
+			{
+				// New syntax: 'verb' and typed parameters
+				$sAction = $actionHandler['verb'];
+				$aParams = array();
+				foreach($actionHandler['params'] as $aDefinition)
+				{
+					$sParamType = array_key_exists('type', $aDefinition) ? $aDefinition['type'] : 'string';
+					switch($sParamType)
+					{
+						case 'int':
+						$value = (int)$aDefinition['value'];
+						break;
+						
+						case 'float':
+						$value = (float)$aDefinition['value'];
+						break;
+						
+						case 'bool':
+						$value = (bool)$aDefinition['value'];
+						break;
+						
+						case 'reference':
+						$value = ${$aDefinition['value']};
+						break;
+						
+						case 'string':
+						default:
+						$value = (string)$aDefinition['value'];
+					}
+					$aParams[] = $value;
+				}
+				$aCallSpec = array($this, $sAction);
+				$bRet = call_user_func_array($aCallSpec, $aParams);
 			}
-			$bRet = call_user_func($aActionCallSpec, $sStimulusCode);
 			// if one call fails, the whole is considered as failed
 			if (!$bRet) $bSuccess = false;
 		}
@@ -2563,6 +2677,15 @@ abstract class DBObject implements iDisplay
 	
 	public function GetHilightClass()
 	{
+		$sCode = $this->ComputeHighlightCode();
+		if($sCode != '')
+		{
+			$aHighlightScale = MetaModel::GetHighlightScale(get_class($this));
+			if (array_key_exists($sCode, $aHighlightScale))
+			{
+				return $aHighlightScale[$sCode]['color'];
+			}
+		}
 		return HILIGHT_CLASS_NONE;
 	}
 

+ 108 - 5
core/metamodel.class.php

@@ -279,6 +279,7 @@ abstract class MetaModel
 	private static $m_aChildClasses = array(); // array of ("classname" => array of "childclass")
 
 	private static $m_aClassParams = array(); // array of ("classname" => array of class information)
+	private static $m_aHighlightScales = array(); // array of ("classname" => array of highlightscale information)
 
 	static public function GetParentPersistentClass($sRefClass)
 	{
@@ -1908,6 +1909,50 @@ abstract class MetaModel
 		self::$m_aTransitions[$sTargetClass][$sStateCode] = array();
 	}
 
+	public static function Init_DefineHighlightScale($aHighlightScale)
+	{
+		$sTargetClass = self::GetCallersPHPClass("Init");
+		self::$m_aHighlightScales[$sTargetClass] = $aHighlightScale;
+	}
+	
+	public static function GetHighlightScale($sTargetClass)
+	{
+		$aScale = array();
+		$aParentScale = array();
+		$sParentClass = self::GetParentPersistentClass($sTargetClass);
+		if (!empty($sParentClass))
+		{
+			// inherit the scale from the parent class
+			$aParentScale = self::GetHighlightScale($sParentClass);
+		}
+		if (array_key_exists($sTargetClass, self::$m_aHighlightScales))
+		{
+			$aScale = self::$m_aHighlightScales[$sTargetClass];
+		}
+		return array_merge($aParentScale, $aScale); // Merge both arrays, the values from the last one have precedence
+	}
+	
+	public static function GetHighlightCode($sTargetClass, $sStateCode)
+	{
+		$sCode = '';
+		if ( array_key_exists($sTargetClass, self::$m_aStates)
+			 && array_key_exists($sStateCode, self::$m_aStates[$sTargetClass])
+			 && array_key_exists('highlight', self::$m_aStates[$sTargetClass][$sStateCode]) )
+		{
+			$sCode = self::$m_aStates[$sTargetClass][$sStateCode]['highlight']['code'];
+		}
+		else
+		{
+			// Check the parent's definition
+			$sParentClass = self::GetParentPersistentClass($sTargetClass);
+			if (!empty($sParentClass))
+			{
+				$sCode = self::GetHighlightCode($sParentClass, $sStateCode);
+			}
+		}
+		return $sCode;
+	}
+	
 	public static function Init_OverloadStateAttribute($sStateCode, $sAttCode, $iFlags)
 	{
 		// Warning: this is not sufficient: the flags have to be copied to the states that are inheriting from this state
@@ -3386,6 +3431,33 @@ abstract class MetaModel
 				{
 					// Do nothing...
 				}
+				else if ($oAttDef instanceof AttributeStopWatch)
+				{
+					$aThresholds = $oAttDef->ListThresholds();
+					if (is_array($aThresholds))
+					{
+						foreach($aThresholds as $iPercent => $aDef)
+						{
+							if (array_key_exists('highlight', $aDef))
+							{
+								if(!array_key_exists('code', $aDef['highlight']))
+								{
+									$aErrors[$sClass][] = "The 'code' element is missing for the 'highlight' property of the $iPercent% threshold in the attribute: '$sAttCode'.";
+									$aSugFix[$sClass][] = "Add a 'code' entry specifying the value of the highlight code for this threshold.";
+								}
+								else
+								{
+									$aScale = self::GetHighlightScale($sClass);
+									if (!array_key_exists($aDef['highlight']['code'], $aScale))
+									{
+										$aErrors[$sClass][] = "'{$aDef['highlight']['code']}' is not a valid value for the 'code' element of the $iPercent% threshold in the attribute: '$sAttCode'.";
+										$aSugFix[$sClass][] = "The possible highlight codes for this class are: ".implode(', ', array_keys($aScale)).".";
+									}
+								}
+							}
+						}						
+					}
+				}
 				else // standard attributes
 				{
 					// Check that the default values definition is a valid object!
@@ -3483,17 +3555,46 @@ abstract class MetaModel
 						}
 					}
 	
-					// Lifcycle - check that the action handlers are defined
+					// Lifecycle - check that the action handlers are defined
 					foreach (self::EnumStates($sClass) as $sStateCode => $aStateDef)
 					{
 						foreach(self::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef)
 						{
-							foreach ($aTransitionDef['actions'] as $sActionHandler)
+							foreach ($aTransitionDef['actions'] as $actionHandler)
+							{
+								if (is_string($actionHandler))
+								{
+									if (!method_exists($sClass, $actionHandler))
+									{
+										$aErrors[$sClass][] = "Unknown function '$sActionHandler' in transition [$sStateCode/$sStimulusCode] for state attribute '$sStateAttCode'";
+										$aSugFix[$sClass][] = "Specify a function which prototype is in the form [public function $sActionHandler(\$sStimulusCode){return true;}]";
+									}
+								}
+								else // if(is_array($actionHandler))
+								{
+									$sActionHandler = $actionHandler['verb'];
+									if (!method_exists($sClass, $sActionHandler))
+									{
+										$aErrors[$sClass][] = "Unknown function '$sActionHandler' in transition [$sStateCode/$sStimulusCode] for state attribute '$sStateAttCode'";
+										$aSugFix[$sClass][] = "Specify a function which prototype is in the form [public function $sActionHandler(...){return true;}]";
+									}
+								}
+							}
+						}
+						if (array_key_exists('highlight', $aStateDef))
+						{
+							if(!array_key_exists('code', $aStateDef['highlight']))
+							{
+								$aErrors[$sClass][] = "The 'code' element is missing for the 'highlight' property of state: '$sStateCode'.";
+								$aSugFix[$sClass][] = "Add a 'code' entry specifying the value of the highlight code for this state.";
+							}
+							else
 							{
-								if (!method_exists($sClass, $sActionHandler))
+								$aScale = self::GetHighlightScale($sClass);
+								if (!array_key_exists($aStateDef['highlight']['code'], $aScale))
 								{
-									$aErrors[$sClass][] = "Unknown function '$sActionHandler' in transition [$sStateCode/$sStimulusCode] for state attribute '$sStateAttCode'";
-									$aSugFix[$sClass][] = "Specify a function which prototype is in the form [public function $sActionHandler(\$sStimulusCode){return true;}]";
+									$aErrors[$sClass][] = "'{$aStateDef['highlight']['code']}' is not a valid value for the 'code' element in the 'highlight' property of state: '$sStateCode'.";
+									$aSugFix[$sClass][] = "The possible highlight codes for this class are: ".implode(', ', array_keys($aScale)).".";
 								}
 							}
 						}
@@ -4718,6 +4819,7 @@ abstract class MetaModel
 				self::$m_aStates = $result['m_aStates'];
 				self::$m_aStimuli = $result['m_aStimuli'];
 				self::$m_aTransitions = $result['m_aTransitions'];
+				self::$m_aHighlightScales = $result['m_aHighlightScales'];
 			}
 			$oKPI->ComputeAndReport('Metamodel APC (fetch + read)');
 		}
@@ -4754,6 +4856,7 @@ abstract class MetaModel
 				$aCache['m_aStates'] = self::$m_aStates; // array of ("classname" => array of "statecode"=>array('label'=>..., attribute_inherit=> attribute_list=>...))
 				$aCache['m_aStimuli'] = self::$m_aStimuli; // array of ("classname" => array of ("stimuluscode"=>array('label'=>...)))
 				$aCache['m_aTransitions'] = self::$m_aTransitions; // array of ("classname" => array of ("statcode_from"=>array of ("stimuluscode" => array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD)))
+				$aCache['m_aHighlightScales'] = self::$m_aHighlightScales; // array of ("classname" => array of higlightcodes)))
 				apc_store($sOqlAPCCacheId, $aCache);
 				$oKPI->ComputeAndReport('Metamodel APC (store)');
 			}

+ 64 - 4
core/ormstopwatch.class.inc.php

@@ -62,12 +62,13 @@ class ormStopWatch
 		return (string) $this->iTimeSpent;
 	}
 
-	public function DefineThreshold($iPercent, $tDeadline = null, $bPassed = false, $bTriggered = false, $iOverrun = null)
+	public function DefineThreshold($iPercent, $tDeadline = null, $bPassed = false, $bTriggered = false, $iOverrun = null, $aHighlightDef = null)
 	{
 		$this->aThresholds[$iPercent] = array(
 			'deadline' => $tDeadline, // unix time (seconds)
 			'triggered' => $bTriggered,
-			'overrun' => $iOverrun
+			'overrun' => $iOverrun,
+			'highlight' => $aHighlightDef, // array('code' => string, 'persistent' => boolean)
 		);
 	}
 
@@ -143,6 +144,30 @@ class ormStopWatch
 			return false;
 		}
 	}
+	
+	public function GetHighlightCode()
+	{
+		$sCode = '';
+		// Process the thresholds in ascending order
+		$aPercents = array();
+		foreach($this->aThresholds as $iPercent => $aDefs)
+		{
+			$aPercents[] = $iPercent;
+		}
+		sort($aPercents, SORT_NUMERIC);
+		foreach($aPercents as $iPercent)
+		{
+			$aDefs = $this->aThresholds[$iPercent];
+			if (array_key_exists('highlight', $aDefs) && is_array($aDefs['highlight']) && $this->IsThresholdPassed($iPercent))
+			{
+				if (($aDefs['highlight']['persistent'] == true) || (($aDefs['highlight']['persistent'] == false) && !is_null($this->iLastStart)))
+				{
+					$sCode = $aDefs['highlight']['code'];
+				}
+			}
+		}
+		return $sCode;
+	}
 
 	public function GetAsHTML($oAttDef, $oHostObject = null)
 	{
@@ -424,9 +449,44 @@ class CheckStopWatchThresholds implements iBackgroundProcess
 							{
 								$sVerb = $aActionData['verb'];
 								$aParams = $aActionData['params'];
-								$sParams = implode(', ', $aParams);
+								$aValues = array();
+								foreach($aParams as $def)
+								{
+									if (is_string($def))
+									{
+										// Old method (pre-2.0.4) non typed parameters
+										$aValues[] = $def;
+									}
+									else // if(is_array($def))
+									{
+										$sParamType = array_key_exists('type', $def) ? $def['type'] : 'string';
+										switch($sParamType)
+										{
+											case 'int':
+												$value = (int)$def['value'];
+												break;
+										
+											case 'float':
+												$value = (float)$def['value'];
+												break;
+										
+											case 'bool':
+												$value = (bool)$def['value'];
+												break;
+										
+											case 'reference':
+												$value = ${$def['value']};
+												break;
+										
+											case 'string':
+											default:
+												$value = (string)$def['value'];
+										}
+										$aValues[] = $value;
+									}
+								}
 								$aCallSpec = array($oObj, $sVerb);
-								call_user_func_array($aCallSpec, $aParams);
+								call_user_func_array($aCallSpec, $aValues);
 							}
 
 							// Mark the threshold as "triggered"

+ 35 - 57
datamodels/2.x/itop-change-mgmt-itil/datamodel.itop-change-mgmt-itil.xml

@@ -201,6 +201,23 @@
       </fields>
       <lifecycle>
         <attribute>status</attribute>
+        <highlight_scale>
+          <item id="approved">
+            <rank>1</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/change-approved.png</icon>
+          </item>
+          <item id="rejected">
+            <rank>2</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/change-rejected.png</icon>
+          </item>
+          <item id="closed">
+            <rank>3</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/change-closed.png</icon>
+          </item>
+        </highlight_scale>
         <stimuli>
           <stimulus id="ev_validate" xsi:type="StimulusUserAction"/>
           <stimulus id="ev_reject" xsi:type="StimulusUserAction"/>
@@ -343,6 +360,9 @@
             <transitions/>
           </state>
           <state id="rejected">
+            <highlight>
+              <code>rejected</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -532,6 +552,9 @@
             <transitions/>
           </state>
           <state id="approved">
+            <highlight>
+              <code>approved</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -594,6 +617,9 @@
             <transitions/>
           </state>
           <state id="notapproved">
+            <highlight>
+              <code>rejected</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -657,6 +683,9 @@
             <transitions/>
           </state>
           <state id="implemented">
+            <highlight>
+              <code>approved</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -719,6 +748,9 @@
             <transitions/>
           </state>
           <state id="monitored">
+            <highlight>
+              <code>approved</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -790,6 +822,9 @@
             <transitions/>
           </state>
           <state id="closed">
+            <highlight>
+              <code>closed</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -932,63 +967,6 @@
 		$this->Set('last_update', time());
 	}]]></code>
         </method>
-        <method id="GetIcon">
-          <comment>/**&#13;
-	 * Get the icon representing this object&#13;
-	 * @param boolean $bImgTag If true the result is a full IMG tag (or an emtpy string if no icon is defined)&#13;
-	 * @return string Either the full IMG tag ($bImgTag == true) or just the path to the icon file&#13;
-	 */</comment>
-          <static>false</static>
-          <access>public</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	public function GetIcon($bImgTag = true)
-	{
-		$sStatus = $this->Get('status');
-		switch($this->GetState())
-		{
-			case 'approved':
-			case 'implemented':
-			case 'monitored':
-			$sIcon = self::MakeIconFromName('change-approved.png');
-			break;
-			
-			case 'rejected':
-			case 'notapproved':
-			$sIcon = self::MakeIconFromName('change-rejected.png');
-			break;
-
-			case 'closed':
-			$sIcon = self::MakeIconFromName('change-closed.png');
-			break;
-
-			default:
-			$sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
-        <method id="MakeIconFromName">
-          <static>true</static>
-          <access>protected</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	protected static function MakeIconFromName($sIconName, $bImgTag = true)
-	{
-		$sIcon = '';
-		if ($sIconName != '')
-		{
-			$sPath = '../env-'.utils::GetCurrentEnvironment().'/itop-change-mgmt-itil/images/'.$sIconName;
-			if ($bImgTag)
-			{
-				$sIcon = "<img src=\"$sPath\" style=\"vertical-align:middle;\"/>";
-			}
-			else
-			{
-				$sIcon  = $sPath;
-			}
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
       </methods>
       <presentation>
         <details>

+ 26 - 57
datamodels/2.x/itop-change-mgmt/datamodel.itop-change-mgmt.xml

@@ -145,6 +145,23 @@
         </field>
       </fields>
       <lifecycle>
+        <highlight_scale>
+          <item id="approved">
+            <rank>1</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/change-approved.png</icon>
+          </item>
+          <item id="rejected">
+            <rank>2</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/change-rejected.png</icon>
+          </item>
+          <item id="closed">
+            <rank>3</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/change-closed.png</icon>
+          </item>
+        </highlight_scale>
         <attribute>status</attribute>
         <stimuli>
           <stimulus id="ev_assign" xsi:type="StimulusUserAction"/>
@@ -340,6 +357,9 @@
             </transitions>
           </state>
           <state id="rejected">
+            <highlight>
+              <code>rejected</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -415,6 +435,9 @@
             </transitions>
           </state>
           <state id="approved">
+            <highlight>
+              <code>approved</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -490,6 +513,9 @@
             </transitions>
           </state>
           <state id="closed">
+            <highlight>
+              <code>closed</code>
+            </highlight>
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -633,63 +659,6 @@
 		$this->Set('last_update', time());
 	}]]></code>
         </method>
-        <method id="GetIcon">
-          <comment>/**&#13;
-	 * Get the icon representing this object&#13;
-	 * @param boolean $bImgTag If true the result is a full IMG tag (or an emtpy string if no icon is defined)&#13;
-	 * @return string Either the full IMG tag ($bImgTag == true) or just the path to the icon file&#13;
-	 */</comment>
-          <static>false</static>
-          <access>public</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	public function GetIcon($bImgTag = true)
-	{
-		$sStatus = $this->Get('status');
-		switch($this->GetState())
-		{
-			case 'approved':
-			case 'implemented':
-			case 'monitored':
-			$sIcon = self::MakeIconFromName('change-approved.png');
-			break;
-			
-			case 'rejected':
-			case 'notapproved':
-			$sIcon = self::MakeIconFromName('change-rejected.png');
-			break;
-
-			case 'closed':
-			$sIcon = self::MakeIconFromName('change-closed.png');
-			break;
-
-			default:
-			$sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
-        <method id="MakeIconFromName">
-          <static>true</static>
-          <access>protected</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	protected static function MakeIconFromName($sIconName, $bImgTag = true)
-	{
-		$sIcon = '';
-		if ($sIconName != '')
-		{
-			$sPath = '../env-'.utils::GetCurrentEnvironment().'/itop-change-mgmt/images/'.$sIconName;
-			if ($bImgTag)
-			{
-				$sIcon = "<img src=\"$sPath\" style=\"vertical-align:middle;\"/>";
-			}
-			else
-			{
-				$sIcon  = $sPath;
-			}
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
       </methods>
       <presentation>
         <details>

+ 45 - 142
datamodels/2.x/itop-incident-mgmt-itil/datamodel.itop-incident-mgmt-itil.xml

@@ -188,11 +188,19 @@
           <thresholds>
             <threshold>
               <percent>75</percent>
+              <highlight>
+                <code>warning</code>
+                <persistent>false</persistent>
+              </highlight> 
               <actions>
 		</actions>
             </threshold>
             <threshold>
               <percent>100</percent>
+              <highlight>
+                <code>critical</code>
+                <persistent>false</persistent>
+              </highlight> 
               <actions>
                 <action>
                   <verb>ApplyStimulus</verb>
@@ -217,11 +225,19 @@
           <thresholds>
             <threshold>
               <percent>75</percent>
+              <highlight>
+                <code>warning</code>
+                <persistent>false</persistent>
+              </highlight> 
               <actions>
 		</actions>
             </threshold>
             <threshold>
               <percent>100</percent>
+              <highlight>
+                <code>critical</code>
+                <persistent>false</persistent>
+              </highlight> 
               <actions>
                 <action>
                   <verb>ApplyStimulus</verb>
@@ -357,6 +373,23 @@
         </field>
       </fields>
       <lifecycle>
+        <highlight_scale>
+          <item id="warning">
+            <rank>1</rank>
+            <color>HIGHLIGHT_CLASS_WARNING</color>
+            <icon>images/incident-deadline.png</icon>
+          </item>
+          <item id="critical">
+            <rank>2</rank>
+            <color>HIGHLIGHT_CLASS_CRITICAL</color>
+            <icon>images/incident-escalated.png</icon>
+          </item>
+          <item id="closed">
+            <rank>3</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/incident-closed.png</icon>
+          </item>
+        </highlight_scale>
         <attribute>status</attribute>
         <stimuli>
           <stimulus id="ev_assign" xsi:type="StimulusUserAction"/>
@@ -481,6 +514,9 @@
             </transitions>
           </state>
           <state id="escalated_tto">
+            <highlight>
+              <code>critical</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -691,6 +727,9 @@
             </transitions>
           </state>
           <state id="escalated_ttr">
+            <highlight>
+              <code>critical</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -898,6 +937,9 @@
             </transitions>
           </state>
           <state id="resolved">
+            <highlight>
+              <code>closed</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -1045,6 +1087,9 @@
             </transitions>
           </state>
           <state id="closed">
+            <highlight>
+              <code>closed</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -1310,148 +1355,6 @@
 		}
 	}]]></code>
         </method>
-        <method id="GetIcon">
-          <comment>/**&#13;
-	 * Get the icon representing this object&#13;
-	 * @param boolean $bImgTag If true the result is a full IMG tag (or an emtpy string if no icon is defined)&#13;
-	 * @return string Either the full IMG tag ($bImgTag == true) or just the path to the icon file&#13;
-	 */</comment>
-          <static>false</static>
-          <access>public</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	public function GetIcon($bImgTag = true)
-	{
-		$sStatus = $this->Get('status');
-		switch($this->GetState())
-		{
-
-			case 'escalated_tto':
-			case 'escalated_ttr':
-			$sIcon = self::MakeIconFromName('incident-escalated.png');
-			break;
-			
-			case 'resolved':
-			case 'closed':
-			$sIcon = self::MakeIconFromName('incident-closed.png');
-			break;
-
-			case 'new':
-			case 'approved':
-			$sIcon = self::MakeIconFromName('incident.png');
-			$iEscalationDeadline = $this->Get('tto_escalation_deadline');
-			if ($iEscalationDeadline != null)
-			{
-				// A SLA is running
-				$oTTOStopWatch = $this->Get('tto');
-				if ($oTTOStopWatch->IsThresholdPassed(100))
-				{
-					$sIcon = self::MakeIconFromName('incident-escalated.png');
-				}
-				else if ($oTTOStopWatch->IsThresholdPassed(75))
-				{
-					$sIcon = self::MakeIconFromName('incident-deadline.png');
-				}
-			}
-			break;
-			
-			case 'assigned':
-			$sIcon = self::MakeIconFromName('incident.png');
-			$iEscalationDeadline = $this->Get('ttr_escalation_deadline');
-			if ($iEscalationDeadline != null)
-			{
-				// A SLA is running
-				$oTTRStopWatch = $this->Get('ttr');
-				if ($oTTRStopWatch->IsThresholdPassed(100))
-				{
-					$sIcon = self::MakeIconFromName('incident-escalated.png');
-				}
-				else if ($oTTRStopWatch->IsThresholdPassed(75))
-				{
-					$sIcon = self::MakeIconFromName('incident-deadline.png');
-				}
-			}
-			break;
-
-			default:
-			$sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
-        <method id="MakeIconFromName">
-          <static>true</static>
-          <access>protected</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	protected static function MakeIconFromName($sIconName, $bImgTag = true)
-	{
-		$sIcon = '';
-		if ($sIconName != '')
-		{
-			$sPath = '../env-'.utils::GetCurrentEnvironment().'/itop-incident-mgmt-itil/images/'.$sIconName;
-			if ($bImgTag)
-			{
-				$sIcon = "<img src=\"$sPath\" style=\"vertical-align:middle;\"/>";
-			}
-			else
-			{
-				$sIcon  = $sPath;
-			}
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
-        <method id="GetHilightClass">
-          <static>false</static>
-          <access>public</access>
-          <type>Overload-iDisplay</type>
-          <code><![CDATA[	public function GetHilightClass()
-	{
-		$sHilightClass = '';
-		switch($this->GetState())
-		{
-            case 'new':
-            case 'approved':
-            $iEscalationDeadline  = $this->Get('tto_escalation_deadline');
-            if ($iEscalationDeadline != null)
-            {
-                  // A SLA is running
-                  $oTTOStopWatch = $this->Get('tto');
-                  if ($oTTOStopWatch->IsThresholdPassed(100))
-                  {
-                    $sHilightClass = HILIGHT_CLASS_CRITICAL;
-                  }
-                  else if ($oTTOStopWatch->IsThresholdPassed(75))
-                  {
-                    $sHilightClass = HILIGHT_CLASS_WARNING;
-                  }
-            }
-            break;
-      
-            case 'assigned':
-            $iEscalationDeadline = $this->Get('ttr_escalation_deadline');
-            if ($iEscalationDeadline != null)
-            {
-                // A SLA is running
-                $oTTRStopWatch = $this->Get('ttr');
-                if ($oTTRStopWatch->IsThresholdPassed(100))
-                {
-                  $sHilightClass = HILIGHT_CLASS_CRITICAL;
-                }
-                else if ($oTTRStopWatch->IsThresholdPassed(75))
-                {
-                  $sHilightClass = HILIGHT_CLASS_WARNING;
-                }
-            }
-            break;		
-			
-			case 'escalated_tto':
-			case 'escalated_ttr':
-			$sHilightClass = HILIGHT_CLASS_CRITICAL;
-			break;
-		}
-		return $sHilightClass;
-	}]]></code>
-        </method>
         <method id="resolveChilds">
           <static>false</static>
           <access>public</access>

+ 29 - 146
datamodels/2.x/itop-request-mgmt-itil/datamodel.itop-request-mgmt-itil.xml

@@ -388,6 +388,23 @@
         </field>
       </fields>
       <lifecycle>
+        <highlight_scale>
+          <item id="warning">
+            <rank>1</rank>
+            <color>HIGHLIGHT_CLASS_WARNING</color>
+            <icon>images/user-request-deadline.png</icon>
+          </item>
+          <item id="critical">
+            <rank>2</rank>
+            <color>HIGHLIGHT_CLASS_CRITICAL</color>
+            <icon>images/user-request-escalated.png</icon>
+          </item>
+          <item id="closed">
+            <rank>3</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/user-request-closed.png</icon>
+          </item>
+        </highlight_scale>
         <attribute>status</attribute>
         <stimuli>
           <stimulus id="ev_assign" xsi:type="StimulusUserAction"/>
@@ -526,6 +543,9 @@
             </transitions>
           </state>
           <state id="escalated_tto">
+            <highlight>
+              <code>critical</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -748,6 +768,9 @@
             </transitions>
           </state>
           <state id="escalated_ttr">
+            <highlight>
+              <code>critical</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -1269,6 +1292,9 @@
             </transitions>
           </state>
           <state id="resolved">
+             <highlight>
+              <code>closed</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -1419,6 +1445,9 @@
             </transitions>
           </state>
           <state id="closed">
+            <highlight>
+              <code>closed</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -1701,152 +1730,6 @@
 		}
 	}]]></code>
         </method>
-        <method id="GetIcon">
-          <comment>/**&#13;
-	 * Get the icon representing this object&#13;
-	 * @param boolean $bImgTag If true the result is a full IMG tag (or an emtpy string if no icon is defined)&#13;
-	 * @return string Either the full IMG tag ($bImgTag == true) or just the path to the icon file&#13;
-	 */</comment>
-          <static>false</static>
-          <access>public</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	public function GetIcon($bImgTag = true)
-	{
-		$sStatus = $this->Get('status');
-		switch($this->GetState())
-		{
-
-			case 'escalated_tto':
-			case 'escalated_ttr':
-			$sIcon = self::MakeIconFromName('user-request-escalated.png');
-			break;
-			
-			case 'resolved':
-			case 'closed':
-			$sIcon = self::MakeIconFromName('user-request-closed.png');
-			break;
-
-			case 'new':
-			case 'approved':
-			$sIcon = self::MakeIconFromName('user-request.png');
-			$iEscalationDeadline = $this->Get('tto_escalation_deadline');
-			if ($iEscalationDeadline != null)
-			{
-				// A SLA is running
-				$oTTOStopWatch = $this->Get('tto');
-				if ($oTTOStopWatch->IsThresholdPassed(100))
-				{
-					$sIcon = self::MakeIconFromName('user-request-escalated.png');
-				}
-				else if ($oTTOStopWatch->IsThresholdPassed(75))
-				{
-					$sIcon = self::MakeIconFromName('user-request-deadline.png');
-				}
-			}
-			break;
-			
-			case 'assigned':
-			$sIcon = self::MakeIconFromName('user-request.png');
-			$iEscalationDeadline = $this->Get('ttr_escalation_deadline');
-			if ($iEscalationDeadline != null)
-			{
-				// A SLA is running
-				$oTTRStopWatch = $this->Get('ttr');
-				if ($oTTRStopWatch->IsThresholdPassed(100))
-				{
-					$sIcon = self::MakeIconFromName('user-request-escalated.png');
-				}
-				else if ($oTTRStopWatch->IsThresholdPassed(75))
-				{
-					$sIcon = self::MakeIconFromName('user-request-deadline.png');
-				}
-			}
-			break;
-
-
-			
-
-
-			
-			default:
-			$sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
-        <method id="MakeIconFromName">
-          <static>true</static>
-          <access>protected</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	protected static function MakeIconFromName($sIconName, $bImgTag = true)
-	{
-		$sIcon = '';
-		if ($sIconName != '')
-		{
-			$sPath = '../env-'.utils::GetCurrentEnvironment().'/itop-request-mgmt-itil/images/'.$sIconName;
-			if ($bImgTag)
-			{
-				$sIcon = "<img src=\"$sPath\" style=\"vertical-align:middle;\"/>";
-			}
-			else
-			{
-				$sIcon  = $sPath;
-			}
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
-        <method id="GetHilightClass">
-          <static>false</static>
-          <access>public</access>
-          <type>Overload-iDisplay</type>
-          <code><![CDATA[	public function GetHilightClass()
-	{
-		$sHilightClass = '';
-		switch($this->GetState())
-		{	
-            case 'new':
-            case 'approved':
-            $iEscalationDeadline  = $this->Get('tto_escalation_deadline');
-            if ($iEscalationDeadline != null)
-            {
-                // A SLA is running
-                $oTTOStopWatch = $this->Get('tto');
-                if ($oTTOStopWatch->IsThresholdPassed(100))
-                {
-                  $sHilightClass = HILIGHT_CLASS_CRITICAL;
-                }
-                else if ($oTTOStopWatch->IsThresholdPassed(75))
-                {
-                  $sHilightClass = HILIGHT_CLASS_WARNING;
-                }
-            }
-            break;
-      
-            case 'assigned':
-            $iEscalationDeadline = $this->Get('ttr_escalation_deadline');
-            if ($iEscalationDeadline != null)
-            {
-                // A SLA is running
-                $oTTRStopWatch = $this->Get('ttr');
-                if ($oTTRStopWatch->IsThresholdPassed(100))
-                {
-                  $sHilightClass = HILIGHT_CLASS_CRITICAL;
-                }
-                else if ($oTTRStopWatch->IsThresholdPassed(75))
-                {
-                  $sHilightClass = HILIGHT_CLASS_WARNING;
-                }
-            }
-            break;  
-			case 'escalated_tto':
-			case 'escalated_ttr':
-			$sHilightClass = HILIGHT_CLASS_CRITICAL;
-			break;
-		}
-		return $sHilightClass;
-	}]]></code>
-        </method>
         <method id="resolveChilds">
           <static>false</static>
           <access>public</access>

+ 56 - 153
datamodels/2.x/itop-request-mgmt/datamodel.itop-request-mgmt.xml

@@ -211,19 +211,27 @@
         <field id="tto" xsi:type="AttributeStopWatch">
           <always_load_in_tables>true</always_load_in_tables>
           <states>
-            <state id="new"/>
-            <state id="escalated_tto"/>
+            <state id="new" />
+            <state id="escalated_tto" />
           </states>
-          <working_time/>
+          <working_time />
           <goal>ResponseTicketTTO</goal>
           <thresholds>
             <threshold>
               <percent>75</percent>
+              <highlight>
+                <code>warning</code>
+                <persistent>false</persistent>
+              </highlight>              
               <actions>
-		</actions>
+              </actions>
             </threshold>
             <threshold>
               <percent>100</percent>
+              <highlight>
+                <code>critical</code>
+                <persistent>false</persistent>
+              </highlight>              
               <actions>
                 <action>
                   <verb>ApplyStimulus</verb>
@@ -238,22 +246,30 @@
         <field id="ttr" xsi:type="AttributeStopWatch">
           <always_load_in_tables>true</always_load_in_tables>
           <states>
-            <state id="new"/>
-            <state id="escalated_tto"/>
-            <state id="assigned"/>
-            <state id="approved"/>
-            <state id="escalated_ttr"/>
+            <state id="new" />
+            <state id="escalated_tto" />
+            <state id="assigned" />
+            <state id="approved" />
+            <state id="escalated_ttr" />
           </states>
-          <working_time/>
+          <working_time />
           <goal>ResponseTicketTTR</goal>
           <thresholds>
             <threshold>
               <percent>75</percent>
+              <highlight>
+                <code>critical</code>
+                <persistent>false</persistent>
+              </highlight>
               <actions>
-		</actions>
+              </actions>
             </threshold>
             <threshold>
               <percent>100</percent>
+              <highlight>
+                <code>critical</code>
+                <persistent>false</persistent>
+              </highlight>
               <actions>
                 <action>
                   <verb>ApplyStimulus</verb>
@@ -388,6 +404,23 @@
         </field>
       </fields>
       <lifecycle>
+        <highlight_scale>
+          <item id="warning">
+            <rank>1</rank>
+            <color>HIGHLIGHT_CLASS_WARNING</color>
+            <icon>images/user-request-deadline.png</icon>
+          </item>
+          <item id="critical">
+            <rank>2</rank>
+            <color>HIGHLIGHT_CLASS_CRITICAL</color>
+            <icon>images/user-request-escalated.png</icon>
+          </item>
+          <item id="closed">
+            <rank>3</rank>
+            <color>HIGHLIGHT_CLASS_NONE</color>
+            <icon>images/user-request-closed.png</icon>
+          </item>
+        </highlight_scale>
         <attribute>status</attribute>
         <stimuli>
           <stimulus id="ev_assign" xsi:type="StimulusUserAction"/>
@@ -523,6 +556,9 @@
             </transitions>
           </state>
           <state id="escalated_tto">
+            <highlight>
+              <code>critical</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -742,6 +778,9 @@
             </transitions>
           </state>
           <state id="escalated_ttr">
+            <highlight>
+              <code>critical</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -1254,6 +1293,9 @@
             </transitions>
           </state>
           <state id="resolved">
+            <highlight>
+              <code>closed</code>
+            </highlight> 
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -1404,6 +1446,9 @@
             </transitions>
           </state>
           <state id="closed">
+            <highlight>
+              <code>closed</code>
+            </highlight>          
             <flags>
               <attribute id="ref">
                 <read_only/>
@@ -1686,148 +1731,6 @@
 		}
 	}]]></code>
         </method>
-        <method id="GetIcon">
-          <comment>/**&#13;
-	 * Get the icon representing this object&#13;
-	 * @param boolean $bImgTag If true the result is a full IMG tag (or an emtpy string if no icon is defined)&#13;
-	 * @return string Either the full IMG tag ($bImgTag == true) or just the path to the icon file&#13;
-	 */</comment>
-          <static>false</static>
-          <access>public</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	public function GetIcon($bImgTag = true)
-	{
-		$sStatus = $this->Get('status');
-		switch($this->GetState())
-		{
-
-			case 'escalated_tto':
-			case 'escalated_ttr':
-			$sIcon = self::MakeIconFromName('user-request-escalated.png');
-			break;
-			
-			case 'resolved':
-			case 'closed':
-			$sIcon = self::MakeIconFromName('user-request-closed.png');
-			break;
-
-			case 'new':
-			case 'approved':
-			$sIcon = self::MakeIconFromName('user-request.png');
-			$iEscalationDeadline = $this->Get('tto_escalation_deadline');
-			if ($iEscalationDeadline != null)
-			{
-				// A SLA is running
-				$oTTOStopWatch = $this->Get('tto');
-				if ($oTTOStopWatch->IsThresholdPassed(100))
-				{
-					$sIcon = self::MakeIconFromName('user-request-escalated.png');
-				}
-				else if ($oTTOStopWatch->IsThresholdPassed(75))
-				{
-					$sIcon = self::MakeIconFromName('user-request-deadline.png');
-				}
-			}
-			break;
-			
-			case 'assigned':
-			$sIcon = self::MakeIconFromName('user-request.png');
-			$iEscalationDeadline = $this->Get('ttr_escalation_deadline');
-			if ($iEscalationDeadline != null)
-			{
-				// A SLA is running
-				$oTTRStopWatch = $this->Get('ttr');
-				if ($oTTRStopWatch->IsThresholdPassed(100))
-				{
-					$sIcon = self::MakeIconFromName('user-request-escalated.png');
-				}
-				else if ($oTTRStopWatch->IsThresholdPassed(75))
-				{
-					$sIcon = self::MakeIconFromName('user-request-deadline.png');
-				}
-			}
-			break;
-
-			default:
-			$sIcon = MetaModel::GetClassIcon(get_class($this), $bImgTag);
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
-        <method id="MakeIconFromName">
-          <static>true</static>
-          <access>protected</access>
-          <type>Overload-DBObject</type>
-          <code><![CDATA[	protected static function MakeIconFromName($sIconName, $bImgTag = true)
-	{
-		$sIcon = '';
-		if ($sIconName != '')
-		{
-			$sPath = '../env-'.utils::GetCurrentEnvironment().'/itop-request-mgmt/images/'.$sIconName;
-			if ($bImgTag)
-			{
-				$sIcon = "<img src=\"$sPath\" style=\"vertical-align:middle;\"/>";
-			}
-			else
-			{
-				$sIcon  = $sPath;
-			}
-		}
-		return $sIcon;
-	}]]></code>
-        </method>
-        <method id="GetHilightClass">
-          <static>false</static>
-          <access>public</access>
-          <type>Overload-iDisplay</type>
-          <code><![CDATA[	public function GetHilightClass()
-	{
-		$sHilightClass = '';
-		switch($this->GetState())
-		{
-			case 'new':
-			case 'approved':
-			$iEscalationDeadline  = $this->Get('tto_escalation_deadline');
-			if ($iEscalationDeadline != null)
-			{
-				// A SLA is running
-                $oTTOStopWatch = $this->Get('tto');
-				if ($oTTOStopWatch->IsThresholdPassed(100))
-				{
-					$sHilightClass = HILIGHT_CLASS_CRITICAL;
-				}
-				else if ($oTTOStopWatch->IsThresholdPassed(75))
-				{
-					$sHilightClass = HILIGHT_CLASS_WARNING;
-				}
-			}
-			break;
-
-			case 'assigned':
-			$iEscalationDeadline = $this->Get('ttr_escalation_deadline');
-			if ($iEscalationDeadline != null)
-			{
-				// A SLA is running
-                $oTTRStopWatch = $this->Get('ttr');
-				if ($oTTRStopWatch->IsThresholdPassed(100))
-				{
-					$sHilightClass = HILIGHT_CLASS_CRITICAL;
-				}
-				else if ($oTTRStopWatch->IsThresholdPassed(75))
-				{
-					$sHilightClass = HILIGHT_CLASS_WARNING;
-				}
-			}
-			break;			
-			
-			case 'escalated_tto':
-			case 'escalated_ttr':
-			$sHilightClass = HILIGHT_CLASS_CRITICAL;
-			break;
-		}
-		return $sHilightClass;
-	}]]></code>
-        </method>
         <method id="resolveChilds">
           <static>false</static>
           <access>public</access>

+ 105 - 5
setup/compiler.class.inc.php

@@ -922,6 +922,15 @@ EOF;
 					{
 						$iPercent = $this->GetPropNumber($oThreshold, 'percent');
 	
+						$oHighlight = $oThreshold->GetUniqueElement('highlight', false);
+						$sHighlight = '';
+						if($oHighlight)
+						{
+							$sCode  = $oHighlight->GetChildText('code');
+							$bPersistent =  $this->GetPropBoolean($oHighlight, 'persistent', false);
+							$sHighlight = "'highlight' => array('code' => '$sCode', 'persistent' => ".($bPersistent ? 'true' : 'false')."), ";
+						}
+						
 						$oActions = $oThreshold->GetUniqueElement('actions');
 						$oActionNodes = $oActions->getElementsByTagName('action');
 						$aActions = array();
@@ -934,7 +943,12 @@ EOF;
 								$oParamNodes = $oParams->getElementsByTagName('param');
 								foreach($oParamNodes as $oParam)
 								{
-									$aActionParams[] = self::QuoteForPHP($oParam->textContent);
+									$sParamType = $oParam->getAttribute('xsi:type');
+									if ($sParamType == '')
+									{
+										$sParamType = 'string';
+									}
+									$aActionParams[] = "array('type' => '$sParamType', 'value' => '".self::QuoteForPHP($oParam->textContent)."')";
 								}
 							}
 							$sActionParams = 'array('.implode(', ', $aActionParams).')';
@@ -942,7 +956,7 @@ EOF;
 							$aActions[] = "array('verb' => $sVerb, 'params' => $sActionParams)";
 						}
 						$sActions = 'array('.implode(', ', $aActions).')';
-						$aThresholds[] = $iPercent." => array('percent' => $iPercent, 'actions' => $sActions)";
+						$aThresholds[] = $iPercent." => array('percent' => $iPercent, $sHighlight 'actions' => $sActions)";
 					}
 					$aParameters['thresholds'] = 'array('.implode(', ', $aThresholds).')';
 				}
@@ -995,6 +1009,7 @@ EOF;
 		// Lifecycle
 		//
 		$sLifecycle = '';
+		$sHighlightScale = '';
 		if ($oLifecycle)
 		{
 			$sLifecycle .= "\t\t// Lifecycle (status attribute: $sStateAttCode)\n";
@@ -1008,7 +1023,57 @@ EOF;
 	
 				$sLifecycle .= "		MetaModel::Init_DefineStimulus(new ".$sStimulusClass."(\"".$sStimulus."\", array()));\n";
 			}
-	
+			$oHighlightScale = $oLifecycle->GetUniqueElement('highlight_scale', false);
+			if ($oHighlightScale)
+			{
+				$sHighlightScale = "\t\t// Higlight Scale\n";
+				$sHighlightScale .= "		MetaModel::Init_DefineHighlightScale( array(\n";
+				
+				$this->CompileFiles($oHighlightScale, $sTempTargetDir.'/'.$sModuleRelativeDir, $sFinalTargetDir.'/'.$sModuleRelativeDir, '');
+				
+				foreach ($oHighlightScale->getElementsByTagName('item') as $oItem)
+				{
+					$sItemCode = $oItem->getAttribute('id');
+					$fRank = (float)$oItem->GetChildText('rank');
+					$sColor = $oItem->GetChildText('color');
+					if (($sIcon = $oItem->GetChildText('icon')) && (strlen($sIcon) > 0))
+					{
+						$sIcon = $sModuleRelativeDir.'/'.$sIcon;
+						$sIcon = "utils::GetAbsoluteUrlModulesRoot().'$sIcon'";
+					}
+					switch($sColor)
+					{
+						// Known PHP constants: keep the literal value as-is
+						case 'HILIGHT_CLASS_CRITICAL':
+						case 'HIGHLIGHT_CLASS_CRITICAL':
+						$sColor = 'HILIGHT_CLASS_CRITICAL';
+						break;
+						
+						case 'HILIGHT_CLASS_OK':
+						case 'HIGHLIGHT_CLASS_OK':
+						$sColor = 'HILIGHT_CLASS_OK';
+						break;
+						
+						case 'HIGHLIGHT_CLASS_WARNING':
+						case 'HILIGHT_CLASS_WARNING':
+						$sColor = 'HILIGHT_CLASS_WARNING';
+						break;
+						
+						case 'HIGHLIGHT_CLASS_NONE':
+						case 'HILIGHT_CLASS_NONE':
+						$sColor = 'HILIGHT_CLASS_NONE';
+						break;
+						
+						default:
+						// Future extension, specify your own color??
+						$sColor = "'".addslashes($sColor)."'";
+					}
+					$sHighlightScale .= "		    '$sItemCode' => array('rank' => $fRank, 'color' => $sColor, 'icon' => $sIcon),\n";
+					
+				}
+				$sHighlightScale .= "		));\n";
+			}
+					
 			$oStates = $oLifecycle->GetUniqueElement('states');
 			foreach ($oStates->getElementsByTagName('state') as $oState)
 			{
@@ -1028,7 +1093,20 @@ EOF;
 				$sLifecycle .= "		MetaModel::Init_DefineState(\n";
 				$sLifecycle .= "			\"".$sState."\",\n";
 				$sLifecycle .= "			array(\n";
-				$sLifecycle .= "				\"attribute_inherit\" => '',\n";
+				$sAttributeInherit = '';
+				//$sAttributeInherit = $oState->GetChildText('inherit_flags', ''); // Seems easy but think about the consequences when applying a delta
+				$sLifecycle .= "				\"attribute_inherit\" => '$sAttributeInherit',\n";
+				$oHighlight = $oState->GetUniqueElement('highlight', false);
+				if ($oHighlight)
+				{
+					$sCode = $oHighlight->GetChildText('code', '');
+					if ($sCode != '')
+					{
+						$sLifecycle .= "				'highlight' => array('code' => '$sCode'),\n";
+					}
+					
+				}
+				
 				$sLifecycle .= "				\"attribute_list\" => array(\n";
 
 				$oFlags = $oState->GetUniqueElement('flags');
@@ -1061,7 +1139,28 @@ EOF;
 					foreach ($oActions->getElementsByTagName('action') as $oAction)
 					{
 						$sVerb = $oAction->GetChildText('verb');
-						$aVerbs[] = "'$sVerb'";
+						$oParams = $oAction->GetOptionalElement('params');
+						$aActionParams = array();
+						if ($oParams)
+						{
+							$oParamNodes = $oParams->getElementsByTagName('param');
+							foreach($oParamNodes as $oParam)
+							{
+								$sParamType = $oParam->getAttribute('xsi:type');
+								if ($sParamType == '')
+								{
+									$sParamType = 'string';
+								}
+								$aActionParams[] = "array('type' => '$sType', 'value' => '".self::QuoteForPHP($oParam->textContent)."')";
+							}
+						}
+						else
+						{
+							// Old (pre 2.0.4) format, when no parameter is specified, assume 1 parameter: reference sStimulusCode
+							$aActionParams[] = "array('type' => 'reference', 'value' => 'sStimulusCode')";
+						}
+						$sActionParams = 'array('.implode(', ', $aActionParams).')';
+						$aVerbs[] = "array('verb' => '$sVerb', 'params' => $sActionParams)";
 					}
 					$sActions = implode(', ', $aVerbs);
 					$sLifecycle .= "		MetaModel::Init_DefineTransition(\"$sState\", \"$sStimulus\", array(\"target_state\"=>\"$sTargetState\", \"actions\"=>array($sActions), \"user_restriction\"=>null));\n";
@@ -1158,6 +1257,7 @@ $sClassParams
 		MetaModel::Init_InheritAttributes();
 $sAttributes
 $sLifecycle
+$sHighlightScale
 $sZlists
 	}