Software AG Products 10.7 | CentraSite for Developers | Custom Reporting Searches | Sample XQueries for Reporting Searches | XQueries for Retrieving Associations
 
XQueries for Retrieving Associations
Let us assume a service serv1 relates to two other services serv2 and serv3 using the predefined association types Contains and Uses respectively.
The following XQuery function finds all registry entries using the Contains association from the service serv1. Initially, XQuery finds the concept corresponding to association type Contains and the service serv1. Associations are stored with the primary objects they start from, that is, the two associations starting from serv1 are stored as cs:association descendants of serv1.
declare namespace cs="http://namespaces.CentraSite.com/Schema/jaxr"
let $concept := collection("CentraSite")/cs:concept
[cs:name/cs:localString = "Contains"]/cs:key
let $service := collection("CentraSite")/
cs:service[cs:name/cs:localString="serv1"]
for $target in $service//cs:association[cs:associationType=$concept]/
cs:targetObject
return collection("CentraSite")/cs:*[cs:key=$target]
This XQuery function returns the complete service serv2. The next XQuery function uses the local function getName to only return the services name.
declare namespace cs="http://namespaces.CentraSite.com/Schema/jaxr"
declare function local:getName($node as node()) as xs:string
{
xs:string($node/cs:name/cs:localString)
}
let $concept := collection("CentraSite")/cs:concept
[cs:name/cs:localString = "Contains"]/cs:key
let $service := collection("CentraSite")/cs:service
[cs:name/cs:localString="serv1"]
for $target in $service//cs:association
[cs:associationType=$concept]/cs:targetObject
return local:getName(collection("CentraSite")/cs:*[cs:key=$target])
The following XQuery function uses another local function followAssocOnce to follow the association.
declare namespace cs="http://namespaces.CentraSite.com/Schema/jaxr"
declare function local:getName($node as node()) as xs:string
{
xs:string($node/cs:name/cs:localString)
}
declare function local:followAssocOnce($entry as node(),
$assoc as xs:string)
as node()*
{
for $key in $entry//cs:association
[cs:associationType=$assoc]/cs:targetObject
return collection("CentraSite")/*[cs:key=$key]
}
let $concept := collection("CentraSite")/cs:concept
[cs:name/cs:localString = "Contains"]/cs:key
let $service := collection("CentraSite")/cs:service
[cs:name/cs:localString="serv1"]
for $target in local:followAssocOnce($service,$concept)
return local:getName($target)
Let us further assume that serv2 points to three other entries, namely the services serv4 and serv5 with Contains association and the service serv6 with Uses association.
The following XQuery function includes a recursive local function followAssocMultiple. This function retrieves all entries that are reachable by following a specific association from a specific entry. When this XQuery function is applied upon the service serv1 and association Contains, it returns the services serv2, serv4, and serv5.
This XQuery function, if applied on an entry that is part of or forms a closed loop system, yields a stack overflow.
declare namespace cs="http://namespaces.CentraSite.com/Schema/jaxr";
declare function local:getName($node as node()) as xs:string
{
xs:string($node/cs:name/cs:localString)
}
declare function local:followAssocOnce($entry as node(),
$assoc as xs:string)
as node()*
{
for $key in $entry//cs:association
[cs:associationType=$assoc]/cs:targetObject
return collection("CentraSite")/*[cs:key=$key]
}
declare function local:followAssocMultiple($entry as node(),
$assoc as xs:string)
as node()*
{
for $target in local:followAssocOnce($entry,$assoc)
return ($target,local:followAssocMultiple($target,$assoc))
}
let $concept := collection("CentraSite")/cs:concept
[cs:name/cs:localString = "Contains"]/cs:key
let $service := collection("CentraSite")/cs:service
[cs:name/cs:localString="serv1"]
for $target in local:followAssocMultiple($service,$concept)
return local:getName($target)
The following XQuery function is applicable on an entry that is part of or forms a closed loop system. This requires that the recursive function takes three parameters. The first parameter is the list of already found nodes. The second parameter holds the current nodes, that is, the nodes found in the previous step. Each time you call the XQuery function, it finds the nodes reached directly from the current nodes. These nodes become the new nodes unless they have previously been found.
declare namespace cs="http://namespaces.CentraSite.com/Schema/jaxr";
declare function local:getName($node as node()) as xs:string
{
xs:string($node/cs:name/cs:localString)
}
declare function local:followAssocOnce($entry as node(),
$assoc as xs:string)
as node()*
{
for $key in $entry//cs:association
[cs:associationType=$assoc]/cs:targetObject
return collection("CentraSite")/*[cs:key=$key]
}
declare function local:followAssocMultiple($current as node()*,
$assoc as xs:string)
as node()* {
let $first := for $node in $current
return local:followAssocOnce($node,$assoc)
return local:followAssocMultipleRecursive((),$first,$assoc)
}
declare function local:followAssocMultipleRecursive(
$old as node()*,
$current as node()*,
$assoc as xs:string) as node()* {
if ($current)
then let $new := for $entry in $current
return local:followAssocOnce($entry,$assoc)
let $nextold := $old union $current
let $nextcurrent := $new except $nextold
return local:followAssocMultipleRecursive($nextold,
$nextcurrent,
$assoc)
else $old
}
let $concept := collection("CentraSite")/cs:concept
[cs:name/cs:localString = "Contains"]/cs:key
let $service := collection("CentraSite")/cs:service
[cs:name/cs:localString="serv1"]
for $target in local:followAssocMultiple($service,$concept)
return local:getName($target)
When following relations in backward direction, retrieval of entries is slightly more complex. To retrieve all entries from which a relation $assoc traverses to a specific entry $entry, find all the entries and check its relations. The following XQuery function uses a local function followAssocOnceBackwards to find all entries starting from serv4, traversing the association Contains in backward direction, and yields serv2.
declare namespace cs="http://namespaces.CentraSite.com/Schema/jaxr"
declare function local:getName($node as node()) as xs:string
{
xs:string($node/cs:name/cs:localString)
}
declare function local:followAssocOnceBackwards($entry as node(),
$assoc as xs:string)
as node()*
{
for $everyentry in collection("CentraSite")/*
for $target in $everyentry//cs:association
[cs:associationType=$assoc]/cs:targetObject
where $target = $entry/cs:key
return $everyentry
}
let $concept := collection("CentraSite")/cs:concept
[cs:name/cs:localString = "Contains"]/cs:key
let $service := collection("CentraSite")/cs:service
[cs:name/cs:localString="serv4"]
for $target in local:followAssocOnceBackwards($service,$concept)
return local:getName($target)