XML Modelization of the relations: reworked toward an asymetric definition (downstream: A impacts B, upstream: B depends on A)

- The queries are developped at runtime (cache)
- More complex algorithm to take into account the legacy type of specification (GetRelationQueries)
- New dictionary naming convention (preserving backward compatibility): "VerbUp" to be replaced by "DownStream
- Temporary hacks to preserve the relation 'depends on', until we have a new GUI
- Special handling for the relation LogicalVolume impacts VirtualDevice which had to be implemented in the bridge module
- Improved the backward compatibility by leaving legacy methods GetRelationQueries returning an empty definition, allowing for an eventual XML redefinition

SVN:trunk[3542]
This commit is contained in:
Romain Quetiez
2015-04-10 10:09:22 +00:00
parent b9b5287b37
commit e64b6d1d98
24 changed files with 3052 additions and 2642 deletions

View File

@@ -2547,10 +2547,20 @@ abstract class DBObject implements iDisplay
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99, &$aResults = array())
{
foreach (MetaModel::EnumRelationQueries(get_class($this), $sRelCode) as $sDummy => $aQueryInfo)
// Temporary patch: until the impact analysis GUI gets rewritten,
// let's consider that "depends on" is equivalent to "impacts/up"
// The current patch has been implemented in DBObject and MetaModel
$sHackedRelCode = $sRelCode;
$bDown = true;
if ($sRelCode == 'depends on')
{
MetaModel::DbgTrace("object=".$this->GetKey().", depth=$iMaxDepth, rel=".$aQueryInfo["sQuery"]);
$sQuery = $aQueryInfo["sQuery"];
$sHackedRelCode = 'impacts';
$bDown = false;
}
foreach (MetaModel::EnumRelationQueries(get_class($this), $sHackedRelCode, $bDown) as $sDummy => $aQueryInfo)
{
MetaModel::DbgTrace("object=".$this->GetKey().", depth=$iMaxDepth, rel=".$aQueryInfo['sQueryDown']);
$sQuery = $bDown ? $aQueryInfo['sQueryDown'] : $aQueryInfo['sQueryUp'];
//$bPropagate = $aQueryInfo["bPropagate"];
//$iDepth = $bPropagate ? $iMaxDepth - 1 : 0;
$iDepth = $iMaxDepth - 1;

View File

@@ -1112,15 +1112,35 @@ abstract class MetaModel
$aClassRelations = array();
foreach($aResult as $sRelCode)
{
$aQueries = self::EnumRelationQueries($sClass, $sRelCode);
if (count($aQueries) > 0)
$aQueriesDown = self::EnumRelationQueries($sClass, $sRelCode);
if (count($aQueriesDown) > 0)
{
$aClassRelations[] = $sRelCode;
}
// Temporary patch: until the impact analysis GUI gets rewritten,
// let's consider that "depends on" is equivalent to "impacts/up"
// The current patch has been implemented in DBObject and MetaModel
if ($sRelCode == 'impacts')
{
$aQueriesUp = self::EnumRelationQueries($sClass, 'impacts', false);
if (count($aQueriesUp) > 0)
{
$aClassRelations[] = 'depends on';
}
}
}
return $aClassRelations;
return $aClassRelations;
}
// Temporary patch: until the impact analysis GUI gets rewritten,
// let's consider that "depends on" is equivalent to "impacts/up"
// The current patch has been implemented in DBObject and MetaModel
if (in_array('impacts', $aResult))
{
$aResult[] = 'depends on';
}
return $aResult;
}
@@ -1131,70 +1151,242 @@ abstract class MetaModel
final static public function GetRelationLabel($sRelCode)
{
return Dict::S("Relation:$sRelCode/VerbUp");
// The legacy convention is confusing with regard to the way we have conceptualized the relations:
// In the former representation, the main stream was named after "up"
// Now, the relation from A to B says that something is transmitted from A to B, thus going DOWNstream as described in a petri net.
$sKey = "Relation:$sRelCode/DownStream";
$sLegacy = Dict::S("Relation:$sRelCode/VerbUp", $sKey);
$sRet = Dict::S($sKey, $sLegacy);
return $sRet;
}
public static function EnumRelationQueries($sClass, $sRelCode)
protected static function ComputeRelationQueries($sRelCode)
{
MyHelpers::CheckKeyInArray('relation code', $sRelCode, self::$m_aRelationInfos);
$aNeighbours = call_user_func_array(array($sClass, 'GetRelationQueriesEx'), array($sRelCode));
// Translate attributes into queries (new style of spec only)
foreach($aNeighbours as $trash => &$aNeighbourData)
$bHasLegacy = false;
$aQueries = array();
foreach (self::GetClasses() as $sClass)
{
try
$aQueries[$sClass]['down'] = array();
if (!array_key_exists('up', $aQueries[$sClass]))
{
if (strlen($aNeighbourData['sQuery']) == 0)
{
$oAttDef = self::GetAttributeDef($sClass, $aNeighbourData['sAttribute']);
if ($oAttDef instanceof AttributeExternalKey)
{
$sTargetClass = $oAttDef->GetTargetClass();
$aNeighbourData['sQuery'] = 'SELECT '.$sTargetClass.' AS o WHERE o.id = :this->'.$aNeighbourData['sAttribute'];
}
elseif ($oAttDef instanceof AttributeLinkedSet)
{
$sLinkedClass = $oAttDef->GetLinkedClass();
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
if ($oAttDef->IsIndirect())
{
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
$oRemoteAttDef = self::GetAttributeDef($sLinkedClass, $sExtKeyToRemote);
$sRemoteClass = $oRemoteAttDef->GetTargetClass();
$aQueries[$sClass]['up'] = array();
}
$aNeighboursDown = call_user_func_array(array($sClass, 'GetRelationQueriesEx'), array($sRelCode));
$aNeighbourData['sQuery'] = "SELECT $sRemoteClass AS o JOIN $sLinkedClass AS lnk ON lnk.$sExtKeyToRemote = o.id WHERE lnk.$sExtKeyToMe = :this->id";
// Translate attributes into queries (new style of spec only)
foreach($aNeighboursDown as $sNeighbourId => $aNeighbourData)
{
$aNeighbourData['sFromClass'] = $aNeighbourData['sDefinedInClass'];
try
{
if (strlen($aNeighbourData['sQueryDown']) == 0)
{
$oAttDef = self::GetAttributeDef($sClass, $aNeighbourData['sAttribute']);
if ($oAttDef instanceof AttributeExternalKey)
{
$sTargetClass = $oAttDef->GetTargetClass();
$aNeighbourData['sToClass'] = $sTargetClass;
$aNeighbourData['sQueryDown'] = 'SELECT '.$sTargetClass.' AS o WHERE o.id = :this->'.$aNeighbourData['sAttribute'];
$aNeighbourData['sQueryUp'] = 'SELECT '.$sClass.' AS o WHERE o.'.$aNeighbourData['sAttribute'].' = :this->id';
}
elseif ($oAttDef instanceof AttributeLinkedSet)
{
$sLinkedClass = $oAttDef->GetLinkedClass();
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
if ($oAttDef->IsIndirect())
{
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
$oRemoteAttDef = self::GetAttributeDef($sLinkedClass, $sExtKeyToRemote);
$sRemoteClass = $oRemoteAttDef->GetTargetClass();
$aNeighbourData['sToClass'] = $sRemoteClass;
$aNeighbourData['sQueryDown'] = "SELECT $sRemoteClass AS o JOIN $sLinkedClass AS lnk ON lnk.$sExtKeyToRemote = o.id WHERE lnk.$sExtKeyToMe = :this->id";
$aNeighbourData['sQueryUp'] = "SELECT $sClass AS o JOIN $sLinkedClass AS lnk ON lnk.$sExtKeyToMe = o.id WHERE lnk.$sExtKeyToRemote = :this->id";
}
else
{
$aNeighbourData['sToClass'] = $sLinkedClass;
$aNeighbourData['sQueryDown'] = "SELECT $sLinkedClass AS o WHERE o.$sExtKeyToMe = :this->id";
$aNeighbourData['sQueryUp'] = "SELECT $sClass AS o WHERE o.id = :this->$sExtKeyToMe";
}
}
else
{
$aNeighbourData['sQuery'] = "SELECT $sLinkedClass AS o WHERE o.$sExtKeyToMe = :this->id";
throw new Exception("Unexpected attribute type for '{$aNeighbourData['sAttribute']}'. Expecting a link set or external key.");
}
}
else
{
throw new Exception("Unexpected attribute type for '{$aNeighbourData['sAttribute']}'. Expecting a link set or external key.");
$oSearch = DBObjectSearch::FromOQL($aNeighbourData['sQueryDown']);
$aNeighbourData['sToClass'] = $oSearch->GetClass();
}
}
catch (Exception $e)
{
throw new Exception("Wrong definition for the relation $sRelCode/{$aNeighbourData['sDefinedInClass']}/{$aNeighbourData['sNeighbour']}: ".$e->getMessage());
}
$sArrowId = $aNeighbourData['sDefinedInClass'].'_'.$sNeighbourId;
$aQueries[$sClass]['down'][$sArrowId] = $aNeighbourData;
// Compute the reverse index
if ($aNeighbourData['sDefinedInClass'] == $sClass)
{
$sFromClass = $aNeighbourData['sFromClass'];
$sToClass = $aNeighbourData['sToClass'];
foreach (self::EnumChildClasses($sToClass, ENUM_CHILD_CLASSES_ALL) as $sSubClass)
{
$aQueries[$sSubClass]['up'][$sArrowId] = $aNeighbourData;
}
}
}
catch (Exception $e)
// Read legacy definitions
// The up/down queries have to be reconcilied, which can only be done later when all the classes have been browsed
//
// The keys used to store a query (up or down) into the array are built differently between the modern and legacy made data:
// Modern way: aQueries[sClass]['up'|'down'][sArrowId], where sArrowId is made of the source class + neighbour id (XML def)
// Legacy way: aQueries[sClass]['up'|'down'][sRemoteClass]
// The modern way does allow for several arrows between two classes
// The legacy way aims at simplifying the transformation (reconciliation between up and down)
if ($sRelCode == 'impacts')
{
$sClassOfDefinition = $aNeighbourData['_legacy_'] ? $sClass.'(or a parent)::GetRelationQueries()' : $aNeighbourData['sDefinedInClass'];
throw new Exception("Wrong definition for the relation $sRelCode/$sClassOfDefinition/{$aNeighbourData['sNeighbour']}: ".$e->getMessage());
$sRevertCode = 'depends on';
$aLegacy = call_user_func_array(array($sClass, 'GetRelationQueries'), array($sRelCode));
foreach($aLegacy as $sId => $aLegacyEntry)
{
$bHasLegacy = true;
$oFilter = DBObjectSearch::FromOQL($aLegacyEntry['sQuery']);
$sRemoteClass = $oFilter->GetClass();
// Determine wether the query is inherited from a parent or not
$bInherited = false;
foreach (self::EnumParentClasses($sClass) as $sParent)
{
if (!isset($aQueries[$sParent]['down'][$sRemoteClass])) continue;
if ($aLegacyEntry['sQuery'] == $aQueries[$sParent]['down'][$sRemoteClass]['sQueryDown'])
{
$bInherited = true;
$aQueries[$sClass]['down'][$sRemoteClass] = $aQueries[$sParent]['down'][$sRemoteClass];
break;
}
}
if (!$bInherited)
{
$aQueries[$sClass]['down'][$sRemoteClass] = array(
'_legacy_' => true,
'sDefinedInClass' => $sClass,
'sFromClass' => $sClass,
'sToClass' => $sRemoteClass,
'sQueryDown' => $aLegacyEntry['sQuery'],
'sNeighbour' => $sRemoteClass // Normalize the neighbour id
);
}
}
$aLegacy = call_user_func_array(array($sClass, 'GetRelationQueries'), array($sRevertCode));
foreach($aLegacy as $sId => $aLegacyEntry)
{
$bHasLegacy = true;
$oFilter = DBObjectSearch::FromOQL($aLegacyEntry['sQuery']);
$sRemoteClass = $oFilter->GetClass();
// Determine wether the query is inherited from a parent or not
$bInherited = false;
foreach (self::EnumParentClasses($sClass) as $sParent)
{
if (!isset($aQueries[$sParent]['up'][$sRemoteClass])) continue;
if ($aLegacyEntry['sQuery'] == $aQueries[$sParent]['up'][$sRemoteClass]['sQueryUp'])
{
$bInherited = true;
$aQueries[$sClass]['up'][$sRemoteClass] = $aQueries[$sParent]['up'][$sRemoteClass];
break;
}
}
if (!$bInherited)
{
$aQueries[$sClass]['up'][$sRemoteClass] = array(
'_legacy_' => true,
'sDefinedInClass' => $sRemoteClass,
'sFromClass' => $sRemoteClass,
'sToClass' => $sClass,
'sQueryUp' => $aLegacyEntry['sQuery'],
'sNeighbour' => $sClass// Normalize the neighbour id
);
}
}
}
else
{
// Cannot take the legacy system into account... simply ignore it
}
} // foreach class
// Perform the up/down reconciliation for the legacy definitions
if ($bHasLegacy)
{
foreach (self::GetClasses() as $sClass)
{
// Foreach "up" legacy query, update its "down" counterpart
if (isset($aQueries[$sClass]['up']))
{
foreach ($aQueries[$sClass]['up'] as $sNeighbourId => $aNeighbourData)
{
if (!$aNeighbourData['_legacy_']) continue; // Skip modern definitions
$sLocalClass = $aNeighbourData['sToClass'];
foreach (self::EnumChildClasses($aNeighbourData['sFromClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass)
{
if (isset($aQueries[$sRemoteClass]['down'][$sLocalClass]))
{
$aQueries[$sRemoteClass]['down'][$sLocalClass]['sQueryUp'] = $aNeighbourData['sQueryUp'];
}
else
{
throw new Exception("Legacy definition of the relation '$sRelCode/$sRevertCode', defined on $sLocalClass (relation: $sRevertCode, inherited to $sClass), missing the counterpart query on class $sRemoteClass ($sRelCode)");
}
}
}
}
// Foreach "down" legacy query, update its "up" counterpart
foreach ($aQueries[$sClass]['down'] as $sNeighbourId => $aNeighbourData)
{
if (!$aNeighbourData['_legacy_']) continue; // Skip modern definitions
$sLocalClass = $aNeighbourData['sFromClass'];
foreach (self::EnumChildClasses($aNeighbourData['sToClass'], ENUM_CHILD_CLASSES_ALL) as $sRemoteClass)
{
$aQueries[$sRemoteClass]['up'][$sLocalClass]['sQueryDown'] = $aNeighbourData['sQueryDown'];
}
}
}
}
return $aQueries;
}
// Merge legacy and new specs
$aLegacy = call_user_func_array(array($sClass, 'GetRelationQueries'), array($sRelCode));
foreach($aLegacy as $sId => $aLegacyEntry)
public static function EnumRelationQueries($sClass, $sRelCode, $bDown = true)
{
static $aQueries = array();
if (!isset($aQueries[$sRelCode]))
{
$aLegacyEntry['_legacy_'] = true;
$aNeighbours[] = array(
'_legacy_' => true,
'sQuery' => $aLegacyEntry['sQuery'],
'sNeighbour' => $sId
);
$aQueries[$sRelCode] = self::ComputeRelationQueries($sRelCode);
}
$sDirection = $bDown ? 'down' : 'up';
if (isset($aQueries[$sRelCode][$sClass][$sDirection]))
{
return $aQueries[$sRelCode][$sClass][$sDirection];
}
else
{
return array();
}
return $aNeighbours;
}
//

View File

@@ -90,5 +90,16 @@
</list>
</presentation>
</class>
<class id="LogicalVolume">
<relations>
<relation id="impacts">
<neighbours>
<neighbour id="VirtualDevice" _delta="define">
<attribute>virtualdevices_list</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
</class>
</classes>
</itop_design>

View File

@@ -13,6 +13,8 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
'itop-storage-mgmt/2.1.0',
'itop-virtualization-mgmt/2.1.0',
),
'mandatory' => false,
'visible' => true, // To prevent auto-install but shall not be listed in the install wizard

View File

@@ -597,11 +597,11 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Class:LogicalInterface/Attribute:virtualmachine_id' => 'Virtuel maskine',
'Class:LogicalInterface/Attribute:virtualmachine_id+' => '',
'Relation:impacts/Description' => 'Elementer berørt af ...',
'Relation:impacts/VerbUp' => 'Påvrikning ...',
'Relation:impacts/VerbDown' => 'Elementer berørt af ...',
'Relation:impacts/DownStream' => 'Påvrikning ...',
'Relation:impacts/UpStream' => 'Elementer berørt af ...',
'Relation:depends on/Description' => 'Elementer, som afhænger af dette element',
'Relation:depends on/VerbUp' => 'Afhænger af ...',
'Relation:depends on/VerbDown' => 'Påvirker ...',
'Relation:depends on/DownStream' => 'Afhænger af ...',
'Relation:depends on/UpStream' => 'Påvirker ...',
'Class:Organization/Attribute:parent_name' => 'Parent name',
'Class:Organization/Attribute:parent_name+' => 'Parent name',
'Class:Organization/Attribute:deliverymodel_name' => 'Leveringsmodel navn',

View File

@@ -1452,6 +1452,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -1854,15 +1866,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="networkdevice">
<query>SELECT NetworkDevice AS nw JOIN lnkConnectableCIToNetworkDevice AS l1 ON l1.networkdevice_id = nw.id WHERE l1.connectableci_id = :this-&gt;id AND l1.connection_type='downlink'</query>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="DatacenterDevice" _delta="define">
<parent>ConnectableCI</parent>
@@ -2383,11 +2398,24 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
<neighbour id="connectableci">
<query>SELECT ConnectableCI AS d JOIN lnkConnectableCIToNetworkDevice AS l1 ON l1.connectableci_id = d.id WHERE l1.networkdevice_id = :this-&gt;id AND l1.connection_type='downlink'</query>
<query_down>SELECT ConnectableCI AS d JOIN lnkConnectableCIToNetworkDevice AS l1 ON l1.connectableci_id = d.id WHERE l1.networkdevice_id = :this-&gt;id AND l1.connection_type='downlink'</query_down>
<query_up>SELECT NetworkDevice AS nw JOIN lnkConnectableCIToNetworkDevice AS l1 ON l1.networkdevice_id = nw.id WHERE l1.connectableci_id = :this-&gt;id AND l1.connection_type='downlink'</query_up>
</neighbour>
</neighbours>
</relation>
@@ -2694,6 +2722,28 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
<neighbour id="hypervisor">
<query_down>SELECT Hypervisor AS o WHERE o.server_id = :this-&gt;id</query_down>
<query_up>SELECT Server AS o WHERE o.id = :this-&gt;server_id</query_up>
</neighbour>
</neighbours>
</relation>
</relations>
</class>
<class id="ApplicationSolution" _delta="define">
<parent>FunctionalCI</parent>
@@ -2822,6 +2872,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -2830,13 +2892,6 @@
</neighbour>
</neighbours>
</relation>
<relation id="depends on">
<neighbours>
<neighbour id="functionalci">
<attribute>functionalcis_list</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
</class>
<class id="BusinessProcess" _delta="define">
@@ -2949,15 +3004,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="applicationsolution">
<attribute>applicationsolutions_list</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="SoftwareInstance" _delta="define">
<parent>FunctionalCI</parent>
@@ -3123,15 +3181,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="functionalci">
<query>SELECT FunctionalCI AS s JOIN SoftwareInstance AS app ON app.system_id = s.id WHERE app.id = :this-&gt;id</query>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="Middleware" _delta="define">
<parent>SoftwareInstance</parent>
@@ -3259,6 +3320,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -3395,6 +3468,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -3531,6 +3616,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -3883,15 +3980,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="middleware">
<attribute>middleware_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="DatabaseSchema" _delta="define">
<parent>FunctionalCI</parent>
@@ -4001,15 +4101,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="dbserver">
<attribute>dbserver_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="WebApplication" _delta="define">
<parent>FunctionalCI</parent>
@@ -4128,15 +4231,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="webserver">
<attribute>webserver_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="Software" _delta="define">
<parent>cmdbAbstractObject</parent>

View File

@@ -424,11 +424,11 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Person:info' => 'Allgemeine Informationen',
'Person:notifiy' => 'Benachrichtigungen',
'Relation:impacts/Description' => 'Elemente betroffen von ...',
'Relation:impacts/VerbUp' => 'Auswirkung ...',
'Relation:impacts/VerbDown' => 'Elemente betroffen von ...',
'Relation:impacts/DownStream' => 'Auswirkung ...',
'Relation:impacts/UpStream' => 'Elemente betroffen von ...',
'Relation:depends on/Description' => 'Elemente, von denen dieses Element abhängt.',
'Relation:depends on/VerbUp' => 'Hängt ab von ...',
'Relation:depends on/VerbDown' => 'Wirkt auf ...',
'Relation:depends on/DownStream' => 'Hängt ab von ...',
'Relation:depends on/UpStream' => 'Wirkt auf ...',
'Class:Organization/Attribute:parent_name' => 'Name der Mutterfirma',
'Class:Organization/Attribute:parent_name+' => 'Name der Mutterfirma',
'Class:Organization/Attribute:parent_id_friendlyname' => 'Parent',

View File

@@ -31,11 +31,11 @@
Dict::Add('EN US', 'English', 'English', array(
'Relation:impacts/Description' => 'Elements impacted by',
'Relation:impacts/VerbUp' => 'Impact...',
'Relation:impacts/VerbDown' => 'Elements impacted by...',
'Relation:impacts/DownStream' => 'Impact...',
'Relation:impacts/UpStream' => 'Elements impacted by...',
'Relation:depends on/Description' => 'Elements impacting',
'Relation:depends on/VerbUp' => 'Depends on...',
'Relation:depends on/VerbDown' => 'Impacts...',
'Relation:depends on/DownStream' => 'Depends on...',
'Relation:depends on/UpStream' => 'Impacts...',
));

View File

@@ -32,11 +32,11 @@
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'Relation:impacts/Description' => 'Elementos Impactados por',
'Relation:impacts/VerbUp' => 'Impacto...',
'Relation:impacts/VerbDown' => 'Elementos Impactados por...',
'Relation:impacts/DownStream' => 'Impacto...',
'Relation:impacts/UpStream' => 'Elementos Impactados por...',
'Relation:depends on/Description' => 'Elementos de los cuales depende',
'Relation:depends on/VerbUp' => 'Depende de...',
'Relation:depends on/VerbDown' => 'Impactos...',
'Relation:depends on/DownStream' => 'Depende de...',
'Relation:depends on/UpStream' => 'Impactos...',
));

View File

@@ -1819,11 +1819,11 @@ Dict::Add('FR FR', 'French', 'Français', array(
'UI-ConfigMgmtMenuOverview-DeviceToRenew' => 'Equipements à remplacer dans 6 mois',
'Menu:UI_WelcomeMenu_AllConfigItems' => 'Résumé',
'Relation:impacts/Description' => 'Eléments impactés par',
'Relation:impacts/VerbUp' => 'Impacte...',
'Relation:impacts/VerbDown' => 'Dépend de...',
'Relation:impacts/DownStream' => 'Impacte...',
'Relation:impacts/UpStream' => 'Dépend de...',
'Relation:depends on/Description' => 'Eléments dont dépend',
'Relation:depends on/VerbUp' => 'Dépend de...',
'Relation:depends on/VerbDown' => 'Impacte...',
'Relation:depends on/DownStream' => 'Dépend de...',
'Relation:depends on/UpStream' => 'Impacte...',
'Menu:ConfigManagement:Typology' => 'Configuration des typologies',
));

View File

@@ -383,11 +383,11 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Class:lnkProcessToSolution/Attribute:reason' => 'Ok',
'Class:lnkProcessToSolution/Attribute:reason+' => '',
'Relation:impacts/Description' => 'Konfigurációs elem működését befolyásolják',
'Relation:impacts/VerbUp' => 'Hatás',
'Relation:impacts/VerbDown' => 'Konfigurációs elem működését befolyásolják',
'Relation:impacts/DownStream' => 'Hatás',
'Relation:impacts/UpStream' => 'Konfigurációs elem működését befolyásolják',
'Relation:depends on/Description' => 'Konfigurációs elemtől függnek',
'Relation:depends on/VerbUp' => 'Függőségek',
'Relation:depends on/VerbDown' => 'Hatások',
'Relation:depends on/DownStream' => 'Függőségek',
'Relation:depends on/UpStream' => 'Hatások',
'Class:Organization/Attribute:parent_name' => 'Felérendelt szervezeti egység neve',
'Class:Organization/Attribute:parent_name+' => '',
'Class:Location/Attribute:org_name' => 'Tulejdonos szevezeti egység neve',

View File

@@ -383,11 +383,11 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Class:lnkProcessToSolution/Attribute:reason' => 'Motivo',
'Class:lnkProcessToSolution/Attribute:reason+' => 'Più informazioni tra il processo di business e la soluzione applicativa',
'Relation:impacts/Description' => 'Elementi impattati da...',
'Relation:impacts/VerbUp' => 'Impatto...',
'Relation:impacts/VerbDown' => 'Elementi impattati da...',
'Relation:impacts/DownStream' => 'Impatto...',
'Relation:impacts/UpStream' => 'Elementi impattati da...',
'Relation:depends on/Description' => 'Elementi di questo elemento dipende da',
'Relation:depends on/VerbUp' => 'Dipende da...',
'Relation:depends on/VerbDown' => 'Impatto...',
'Relation:depends on/DownStream' => 'Dipende da...',
'Relation:depends on/UpStream' => 'Impatto...',
'Class:Organization/Attribute:parent_name' => 'Parent name',
'Class:Organization/Attribute:parent_name+' => 'Name of the parent organization',
'Class:Location/Attribute:org_name' => 'Nome dell\'organizzazione',

View File

@@ -595,11 +595,11 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Class:LogicalInterface/Attribute:virtualmachine_id' => '仮想マシン',
'Class:LogicalInterface/Attribute:virtualmachine_id+' => '',
'Relation:impacts/Description' => 'インパクトを受ける要素',
'Relation:impacts/VerbUp' => 'インパクト...',
'Relation:impacts/VerbDown' => 'インパクトを受ける要素',
'Relation:impacts/DownStream' => 'インパクト...',
'Relation:impacts/UpStream' => 'インパクトを受ける要素',
'Relation:depends on/Description' => 'この要素が依存している要素',
'Relation:depends on/VerbUp' => '依存...',
'Relation:depends on/VerbDown' => 'インパクト...',
'Relation:depends on/DownStream' => '依存...',
'Relation:depends on/UpStream' => 'インパクト...',
'Class:Organization/Attribute:parent_name' => '親名前',
'Class:Organization/Attribute:parent_name+' => '親組織の名前',
'Class:Organization/Attribute:deliverymodel_name' => '提供モデル名',

View File

@@ -34,11 +34,11 @@
Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Relation:impacts/Description' => 'Elementen hebben impact op',
'Relation:impacts/VerbUp' => 'Impact...',
'Relation:impacts/VerbDown' => 'Elementen...',
'Relation:impacts/DownStream' => 'Impact...',
'Relation:impacts/UpStream' => 'Elementen...',
'Relation:depends on/Description' => 'Elementen waarvan dit element afhankelijk van is',
'Relation:depends on/VerbUp' => 'Is afhankelijk van...',
'Relation:depends on/VerbDown' => 'Impacts...',
'Relation:depends on/DownStream' => 'Is afhankelijk van...',
'Relation:depends on/UpStream' => 'Impacts...',
));

View File

@@ -31,11 +31,11 @@
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Relation:impacts/Description' => 'Elementos impactados por',
'Relation:impacts/VerbUp' => 'Impacto...',
'Relation:impacts/VerbDown' => 'Elementos impactados por...',
'Relation:impacts/DownStream' => 'Impacto...',
'Relation:impacts/UpStream' => 'Elementos impactados por...',
'Relation:depends on/Description' => 'Elementos estes, que dependem deste elemento',
'Relation:depends on/VerbUp' => 'Depende de...',
'Relation:depends on/VerbDown' => 'Impactos...',
'Relation:depends on/DownStream' => 'Depende de...',
'Relation:depends on/UpStream' => 'Impactos...',
));

View File

@@ -26,11 +26,11 @@
Dict::Add('RU RU', 'Russian', 'Русский', array(
'Relation:impacts/Description' => 'Элементы, на которые влияет',
'Relation:impacts/VerbUp' => 'Влияние...',
'Relation:impacts/VerbDown' => 'Элементы, на которые влияет...',
'Relation:impacts/DownStream' => 'Влияние...',
'Relation:impacts/UpStream' => 'Элементы, на которые влияет...',
'Relation:depends on/Description' => 'Элементы, от которых зависит',
'Relation:depends on/VerbUp' => 'Зависимость...',
'Relation:depends on/VerbDown' => 'Влияние...',
'Relation:depends on/DownStream' => 'Зависимость...',
'Relation:depends on/UpStream' => 'Влияние...',
));

View File

@@ -32,11 +32,11 @@
Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Relation:impacts/Description' => 'Etkilenen kalemler',
'Relation:impacts/VerbUp' => 'Etkiler...',
'Relation:impacts/VerbDown' => 'Etkilenenler...',
'Relation:impacts/DownStream' => 'Etkiler...',
'Relation:impacts/UpStream' => 'Etkilenenler...',
'Relation:depends on/Description' => 'Bu kaleme bağımlı olan kalemler',
'Relation:depends on/VerbUp' => 'Bağımlı olanlar...',
'Relation:depends on/VerbDown' => 'Etkiledikleri...',
'Relation:depends on/DownStream' => 'Bağımlı olanlar...',
'Relation:depends on/UpStream' => 'Etkiledikleri...',
));

View File

@@ -32,11 +32,11 @@
Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Relation:impacts/Description' => '被影响的元素',
'Relation:impacts/VerbUp' => '影响...',
'Relation:impacts/VerbDown' => '被影响的元素...',
'Relation:impacts/DownStream' => '影响...',
'Relation:impacts/UpStream' => '被影响的元素...',
'Relation:depends on/Description' => '该元素依赖的元素...',
'Relation:depends on/VerbUp' => '依赖于...',
'Relation:depends on/VerbDown' => '影响...',
'Relation:depends on/DownStream' => '依赖于...',
'Relation:depends on/UpStream' => '影响...',
));

View File

@@ -531,10 +531,12 @@
<relation id="impacts">
<neighbours>
<neighbour id="datacenterdevice">
<query>SELECT DatacenterDevice WHERE powerA_id = :this-&gt;id OR powerB_id = :this-&gt;id</query>
<query_down>SELECT DatacenterDevice WHERE powerA_id = :this-&gt;id OR powerB_id = :this-&gt;id</query_down>
<query_up>SELECT PowerConnection WHERE id = :this-&gt;powerA_id OR id = :this-&gt;powerB_id</query_up>
</neighbour>
<neighbour id="pdu">
<query>SELECT PDU WHERE powerstart_id = :this-&gt;id</query>
<query_down>SELECT PDU WHERE powerstart_id = :this-&gt;id</query_down>
<query_up>SELECT PowerConnection WHERE id = :this-&gt;powerstart_id</query_up>
</neighbour>
</neighbours>
</relation>
@@ -895,15 +897,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="powerconnection">
<attribute>powerstart_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
</classes>
<menus>

View File

@@ -235,6 +235,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -477,6 +489,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -718,6 +742,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -959,6 +995,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -1058,15 +1106,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="tapelibrary">
<attribute>tapelibrary_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="NASFileSystem" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -1171,15 +1222,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="nas">
<attribute>nas_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="FiberChannelInterface" _delta="define">
<parent>NetworkInterface</parent>
@@ -1429,6 +1483,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -1437,13 +1503,6 @@
</neighbour>
</neighbours>
</relation>
<relation id="depends on">
<neighbours>
<neighbour id="storagesystem">
<attribute>storagesystem_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
</class>
<class id="lnkServerToVolume" _delta="define">

View File

@@ -232,6 +232,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -378,6 +390,18 @@
</items>
</list>
</presentation>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
<relations>
<relation id="impacts">
<neighbours>
@@ -386,13 +410,6 @@
</neighbour>
</neighbours>
</relation>
<relation id="depends on">
<neighbours>
<neighbour id="server">
<attribute>server_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
</class>
<class id="Farm" _delta="define">
@@ -512,15 +529,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="hypervisor">
<attribute>hypervisor_list</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="VirtualMachine" _delta="define">
<parent>VirtualDevice</parent>
@@ -751,15 +771,18 @@
</items>
</list>
</presentation>
<relations>
<relation id="depends on">
<neighbours>
<neighbour id="virtualhost">
<attribute>virtualhost_id</attribute>
</neighbour>
</neighbours>
</relation>
</relations>
<methods>
<method id="GetRelationQueries">
<comment>/**
* Placeholder for backward compatibility (iTop &lt;= 2.1.0)
* in case an extension attempts to redefine this function...
*/</comment>
<static>true</static>
<access>public</access>
<type>Overload-DBObject</type>
<code><![CDATA[ public static function GetRelationQueries($sRelCode){return parent::GetRelationQueries($sRelCode);} ]]></code>
</method>
</methods>
</class>
<class id="LogicalInterface" _delta="define">
<parent>IPInterface</parent>

File diff suppressed because it is too large Load Diff

View File

@@ -530,7 +530,8 @@ function DisplayRelationDetails($oPage, $sRelCode, $sContext)
$oPage->add("<ul>\n");
foreach ($aRelQueries as $sRelKey => $aQuery)
{
$sQuery = isset($aQuery['sQuery']) ? $aQuery['sQuery'] : '';
$sQueryDown = isset($aQuery['sQueryDown']) ? $aQuery['sQueryDown'] : '';
$sQueryUp = isset($aQuery['sQueryUp']) ? $aQuery['sQueryUp'] : '';
$sAttribute = isset($aQuery['sAttribute']) ? $aQuery['sAttribute'] : '';
/*
if ($aQuery['bPropagate'])
@@ -542,7 +543,7 @@ function DisplayRelationDetails($oPage, $sRelCode, $sContext)
$oPage->add("<li>".Dict::Format('UI:Schema:RelationDoesNotPropagate', $sRelKey, $iDistance, $sQuery)."</li>\n");
}
*/
$sLabel = (strlen($sQuery) > 0) ? $sQuery : $sAttribute;
$sLabel = (strlen($sQueryDown) > 0) ? $sQueryDown : $sAttribute;
if ($aQuery['_legacy_'])
{
$sLabel .= ' (<b>Old style specification</b>: it is recommended to upgrade to XML)';

View File

@@ -1420,30 +1420,31 @@ EOF;
if ($oNeighbour->tagName != 'neighbour') continue;
$sNeighbourId = $oNeighbour->getAttribute('id');
if (($oNeighbour->GetChildText('query') == '') && ($oNeighbour->GetChildText('attribute') == ''))
if (($oNeighbour->GetChildText('query_down') != '') && ($oNeighbour->GetChildText('query_up') == ''))
{
throw new DOMFormatException("Relation '$sRelationId': either a query or an attribute must be specified");
throw new DOMFormatException("Relation '$sRelationId/$sNeighbourId': missing the query_up specification");
}
if (($oNeighbour->GetChildText('query') != '') && ($oNeighbour->GetChildText('attribute') != ''))
if (($oNeighbour->GetChildText('query_up') != '') && ($oNeighbour->GetChildText('query_down') == ''))
{
throw new DOMFormatException("Relation '$sRelationId': both a query and and attribute have been specified... which one should be used?");
throw new DOMFormatException("Relation '$sRelationId/$sNeighbourId': missing the query_down specification");
}
if (($oNeighbour->GetChildText('query_down') == '') && ($oNeighbour->GetChildText('attribute') == ''))
{
throw new DOMFormatException("Relation '$sRelationId/$sNeighbourId': either a query or an attribute must be specified");
}
if (($oNeighbour->GetChildText('query_down') != '') && ($oNeighbour->GetChildText('attribute') != ''))
{
throw new DOMFormatException("Relation '$sRelationId/$sNeighbourId': both a query and and attribute have been specified... which one should be used?");
}
$aData = array(
'_legacy_' => false,
'sDefinedInClass' => $sClass,
'sNeighbour' => $sNeighbourId,
'sQuery' => $oNeighbour->GetChildText('query'),
'sQueryDown' => $oNeighbour->GetChildText('query_down'),
'sQueryUp' => $oNeighbour->GetChildText('query_up'),
'sAttribute' => $oNeighbour->GetChildText('attribute'),
);
$oReverse = $oNeighbour->GetOptionalElement('reverse');
if ($oReverse)
{
$aData['sReverseClass'] = $oReverse->GetChildText('source_class');
$aData['sReverseRelation'] = $oReverse->GetChildText('relation');
$aData['sReverseNeighbour'] = $oReverse->GetChildText('neighbour');
}
$oRedundancy = $oNeighbour->GetOptionalElement('redundancy');
if ($oRedundancy)
{