Understanding How Association Paths Are Evaluated

AssociationPathLevel

To understand how an association path is evaluated, we must consider each association path level that is specified. The AssociationPathLevel specifies an association name and an associated object that is evaluated, as well as optional attribute criteria that the associated objects must meet to be selected.
The first AssociationPathLevel in AssociationPath sets the context for the request. It specifies the association that an object must have defined to be evaluated. When considered in the context of Object, the syntax of the first AssociationPathLevel looks like the following:
Object[AssociationName/AssociatedObject[AttributeCriteria]]
Object can be the same metadata type name that is specified in the GetMetadataObjects TYPE parameter, a subtype of the metadata type in TYPE, or an asterisk, which defaults to the value in the TYPE parameter. The value that you specify in Object indicates what association names are valid. In the first AssociationPathLevel, the following is true:
  • If Object is a metadata type, then AssociationName must be an association name that is valid for that metadata type as defined in the SAS Metadata Model. For example, if Object is Report, then AssociationName must be an association name that is defined for the Report metadata type in the SAS Metadata Model.
  • If Object is an *, then AssociationName must be an association name that is valid for the metadata type specified in the TYPE parameter.
The AssociatedObject in the AssociationPathLevel specification can also be a metadata type name or an asterisk. However, in this position, the specified value stipulates whether associated objects of one metadata type should be evaluated, or, that associated objects of all of the potential associated metadata types defined for the association name should be evaluated. For example:
  • When AssociatedObject is a metadata type, this says, “Give me only object instances of this metadata type that are related under the specified association name.”
  • When AssociatedObject is an asterisk, this says “Give me object instances of all potential metadata types that are defined for the specified association name.”
Consider the following AssociationPathLevel specifications to understand how the asterisk and metadata type names are evaluated in the Object and AssociatedObject positions. For these examples, assume that Report is the metadata type specified in the TYPE parameter.
*[ReportLocation/*]

Report[ReportLocation/Email]
The first specification selects objects of the metadata type specified in the TYPE parameter (Report) that have a ReportLocation association and associated objects of any of the metadata types that are valid for the ReportLocation association name. The ReportLocation association name supports associations to objects of 19 metadata types.
The second specification selects Report objects that have a ReportLocation association to an Email object. (Email is one of the 19 supported associated metadata types.)
If a subtype were specified in either the Object or AssociatedObject positions, then the SAS Metadata Server would select only objects and associated objects of the specified subtype. Report is a subtype of the Classifier metadata type. If Classifier were the metadata type specified in the TYPE parameter, the first specification above would apply to the Classifier metadata type. The second specification would still only apply to Report objects.
The AttributeCriteria component in AssociationPathLevel further limits the Objects that are selected to objects whose associated objects meet the specified attribute criteria. For example, consider the following request:
Report[ReportLocation/Document[@TextType='XML']]
The attribute criteria limit the Report objects that are selected to objects that have associated Document objects that have the attribute TextType="XML". When attribute criteria are specified in a query that has an * in the AssociatedObject component, the attribute criteria are applied to all associated objects.
Subsequent AssociationPathLevels in an AssociationPath get their context from the AssociatedObject in the preceding level.
  • When the preceding associated object is a metadata type, AssociationName must be an association name that is valid for that metadata type.
  • When the preceding associated object is an *, AssociationName can be any association name defined for one of the metadata types supported by the preceding association name.
Consider the following AssociationPath. The AssociationPathLevels are separated by a / (slash):
Report[ReportLocation/Document[@TextType='XML']/AssociationName/AssociatedObject]
AssociationName must be an association that is valid for the Document metadata type. AssociatedObject must be a metadata type that is supported by AssociationName or an *.
Consider the following AssociationPath:
Report[ReportLocation/*/AssociationName/AssociatedObject]
AssociationName can be an association name that is valid for any of the 19 metadata types supported by the ReportLocation association. AssociatedObject must be a metadata type that is supported by AssociationName or an *.
The following is an example of an AssociationPath that specifies multiple AssociationPathLevels and specifies metadata types in the AssociatedObject positions:
Report[ResponsibleParties/ResponsibleParty/Persons/Person
/Locations/Location[@Area='New York']]
The request selects Report objects that have a ResponsibleParties association to a ResponsibleParty object that has a Persons association to a Person who has a Locations association to a Location object that has the attribute value Area=“New York”. It has three AssociationPathLevels:
  1. ResponsibleParties/ResponsibleParty
  2. Persons/Person
  3. Locations/Location
The following is an example of an AssociationPath that specifies multiple AssociationPathLevels and specifies asterisks in the AssociatedObject positions:
Report[ResponsibleParties/*[@Role='OWNER']/Persons/*[@Name='John Doe']]
The request selects Report objects that have a ResponsibleParties association to any object that has a Role attribute value of Owner and a Persons association to any object that has a Name attribute value of John Doe. It has two AssociationPathLevels:
  1. ResponsibleParties/*
  2. Persons/*

Effect of OMI_INCLUDE_SUBTYPES Flag on an Association Path

Setting the OMI_INCLUDE_SUBTYPES (16) flag with OMI_XMLSELECT in the GetMetadataObjects method can drastically alter the results. When OMI_INCLUDE_SUBTYPES is set, the SAS Metadata Server applies the specified selection criteria to objects of the metadata types specified in Object and AssociatedObject, and to all of their subtypes.
If the metadata types have no subtypes defined for them in the SAS Metadata Model (neither Report nor Person have subtypes defined), the flag has no effect. However, some metadata types, such as Classifier, have many subtypes. The ability to get subtypes is useful when you want to get objects of similar metadata types that have common properties. Consider the following request:
Classifier[ResponsibleParties/*[@Role='OWNER']/Persons/*[@Name='John Doe']]
When OMI_INCLUDE_SUBTYPES is set, this request returns all Classifier objects, and objects of its subtypes Cube, Dimension, DataTable, ExternalTable, JoinTable, PhysicalTable, QueryTable, RelationalTable, Report, SharedDimension, TableCollection, and WorkTable objects that are owned by John Doe.
To determine what metadata types have subtypes, see the SAS Metadata Model documentation.

Understanding How Concatenated Association Paths Are Evaluated

An <XMLSELECT search="criteria"/> search string that includes concatenated AssociationPath criteria must specify an association name that is valid for the primary Object component in each AssociationPath.
  • If Object is a metadata type, then all association paths must begin with an association name that is valid for that metadata type.
  • If Object is an *, then each association path must begin with an association name that is valid for the metadata type specified in the TYPE parameter.
  • If Object is an * and the OMI_INCLUDE_SUBTYPES flag is set, then each association path must begin with an association name that is valid for the metadata type specified in the TYPE parameter or one of its subtypes.
In SAS 9.3, the search syntax supports explicit AND and OR operators between AssociationPath components. If an operator is omitted, the AssociationPath components are joined by an implied AND operator.
When the AND operator is specified or implied, only objects that meet the criteria in the combined AssociationPath components are selected.
The following table summarizes the evaluation algorithm used when multiple association paths are concatenated with the AND logical operator. If any association path criteria evaluates to False, then the concatenated association path criteria is False.
Search= “*
[path]
lop
[path]
lop
[path]
”=result
[True]
and
[True]
=True
[True]
and
[False]
=False
[False]
and
[False]
=False
[True]
and
[True]
and
[True]
=True
[True]
and
[True]
and
[False]
=False
[True]
and
[False]
and
[False]
=False
[False]
and
[False]
and
[False]
=False
The following table summarizes the evaluation algorithm used when multiple association paths are concatenated with the OR logical operator. Only one association path criteria must be True for the concatenated association path criteria to be True.
search=“*
[path]
lop
[path]
lop
[path]
”=result
[True]
or
[True]
=True
[True]
or
[False]
=True
[False]
or
[False]
=False
[True]
or
[True]
or
[True]
=True
[True]
or
[True]
or
[False]
=True
[True]
or
[False]
or
[False]
=True
[False]
or
[False]
or
[False]
=False
The following table summarizes the evaluation algorithm used when multiple association paths are concatenated with both the AND and OR logical operators. Paths that are separated by an AND logical operator are treated as if they have parenthesis around them. That is, they are read as a set, and they must both be true to evaluate as True. Otherwise, they evaluate to False. When OR is used between association paths, only one path must be True to return a True.
search=“*
[path1]
lop
[path2]
lop
[path3]
”=result
[True]
and
[True]
or
[True]
True
[True]
and
[True]
or
[False]
True
[True]
and
[False]
or
[True]
True
[True]
or
[True]
and
[False]
True
[False]
or
[True]
and
[False]
False
[False]
or
[False]
and
[False]
False
When the OMI_INCLUDE_SUBTYPES flag is set, only objects that have all of the specified association names are tested for a match.
Example 1:
  • Object 1 and Object 2 are subtypes of *. Object 1 has valid associations to associationname1 and associationname2. Object 2 has valid associations to associationname3 and associationname4.
  • Query: search="*[associationname1/object][associationname2/object]"
    Result: Only Object 1 is returned.
  • Query: search="*[associationname3/object][associationname4/object]"
    Result: Only Object 2 is returned.
  • Query: search="*[associationname1/object][associationname4/object]"
    Result: Neither object is returned.
Example 2:
  • Object 1 and Object 2 are subtypes of *. Object 1 has valid associations to associationname1, associationname2, and associationname3. Object 2 has valid associations to associationname2, associationname3, and associationname4.
  • Query: search="*[associationname2/object][associationname3/object]"
    Result: Selects Object 1 and Object 2.
When the OR logical operator is specified, objects must meet the criteria in one of the specified AssociationPath components to be selected.
Example 3:
  • Object 1 has a valid association to associationname1 and associationname2. Object 2 has a valid association to associationname2 and associationname3.
  • Query: search="*[associationname2/object] or [associationname3/object]"
    Result: Selects Object 1 and Object 2.

NOT Function in the AssociationPath Component

Beginning in SAS 9.3, the XMLSELECT search syntax supports a NOT function for AssociationPath criteria. The NOT function can be specified in the syntax to select all objects of the specified metadata type that do not have a specified AssociationPath.
A Search expression that specifies the NOT function takes the following form:
 object[not(AssociationName/AssociatedObject)]
 object[not(AssociationName/AssociatedObject[AttributeCriteria])]
 object[not(AssociationPathLevel1/AssociationPathLeveln)]
The NOT syntax can be specified only for a complete AssociationPath. A syntax error is returned when the NOT function parameter does not contain the complete AssociationPath, as shown in these examples:
 object[not(AssociationPathLevel)/AssociationPathLevel]
 object[AssociationPathLevel/not(AssociationPathLevel)]
When more than one AssociationPathLevel is specified in an AssociationPath, it is better to use specific object types between each AssociationPathLevel instead of an * (asterisk). Using an asterisk between each AssociationPathLevel can cause misleading results. When * is specified between association path levels, some objects might be returned because the next association level is not valid for the associated object, rather than because an associated object is not found for the next level.
The NOT function can find incomplete or obsolete metadata. For example, the following specification returns PhysicalTable objects that do not have any Column objects defined:
search="PhysicalTable[not(Columns/Column)]"
The following request finds SASLibrary objects that are missing a UsingPackages association to a Directory or DatabaseSchema object:
search="SASLibrary[not(UsingPackages/Directory)][not(UsingPackages/DatabaseSchema)]"
The following request finds Property objects that do not have an association to an object. The use of the * in the next request is valid because the Property metadata type supports an AssociatedObject association to all metadata types.
search="Property[not(AssociatedObject/*)]"
However, a Property object that is returned by this request does not necessarily represent an orphaned Property object. A Property object can have a PropertySets association to a PropertySet, or a PropertyGroups association to a PropertyGroup, instead of being associated directly with an object.
The following is an example of a search string that specifies two AssociationPathLevel values:
search="Property[not(AssociatedObject/*/AssociatedFile/File)]"
This request is problematic. A Property object can be associated through the AssociatedObject association to all object types. But, not all object types can be associated to the next level AssociatedFile association. For example, a Cube object has a valid association to the AssociatedFile association, and a PhysicalTable object does not. When an object from the previous AssociationPathLevel is filtered by an incompatible association at the next level, no associated objects can be found.
For more meaningful output, here is a better way to code this request:
search="Property[not(AssociatedObject/Cube/AssociatedFile/File)]     
   [not(AssociatedObject/PhysicalTable)]"
In this example, the first criteria specifies to return Property objects that are not associated to a Cube object through the AssociatedObject association and not associated to a File object through the AssociatedFile association. The second criteria specifies to return Property objects that are not associated to a PhysicalTable object through the AssociatedObject association. Because the criteria are concatenated with an implied AND operator, an object must meet both criteria to be returned.
For an example of a GetMetadataObjects request that specifies the NOT function, see Example of Getting Objects That Do Not Have a Specified Association.