For those interested here is the end resultAssuming a model like
Product 0..*----0..1 Category
Category "0..1 ParentCategory" ----- "0..* ChildCategory" Category
If you want to find all products that belong to all child categories of a parent category you can do Ocl like:
Product.allInstances->select( p | p.Category.IsParentInTree(p.Category, Category.objectFromExternalId('1!1'), 'ParentCategory')
Any ideas on how to make this more efficient welcome, however, the Ocl must be based from the Product class.
Hope this is useful to someone....
Nick
procedure OclParentInTree.Evaluate(Parameters: IOclOperationParameters);
var
ObjectToFind: IObject;
CallingObject: IObject;
AssociationName: string;
CallingObjectElement: IElement;
ObjectToFindElement: IElement;
IsInTree: Boolean;
begin
CallingObjectElement := Parameters.Values[1].Element;
ObjectToFindElement := Parameters.Values[2].Element;
CallingObject := CallingObjectElement as IObject;
ObjectToFind := ObjectToFindElement as IObject;
AssociationName := Support.GetAsString(Parameters.Values[3]);
IsInTree := RecurseTree(CallingObject, AssociationName, ObjectToFind);
Support.MakeNewBoolean(Parameters.Result, IsInTree );
end;
procedure OclParentInTree.Init;
var
OclParameters: array of IOclType;
begin
SetLength(OclParameters, 4);
OclParameters[0] := Support.ObjectType;
OclParameters[1] := Support.ObjectType;
OclParameters[2] := Support.ObjectType;
OclParameters[3] := Support.StringType;
InternalInit('IsParentInTree', OclParameters, Support.BooleanType);
end;
function OclParentInTree.RecurseTree(CallingObject: IObject;
AssociationName: string; ObjectToFind: Iobject): Boolean;
var
ObjectToFindId, CallingObjectId: string;
begin
ObjectToFindId := support.ExternalIdService.IdForObject(ObjectToFind);
CallingObjectid := support.ExternalIdService.IdForObject(CallingObject);
if (CallingObjectId = ObjectToFindId) then
Result := True
else
begin
try
Result := RecurseTree(CallingObject.Properties.Item[AssociationName] as IObject, AssociationName, ObjectToFind);
except
Result := False;
end;
end;
end;