Custom OCL Operation
CapableObjects Forums
Home       Members    Calendar    Who's On
Welcome Guest ( Login | Register )
        



Custom OCL Operation Expand / Collapse
Author
Message
Posted 2008-12-16 14:21:42
Forum Guru

Forum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum Guru

Group: Forum Members
Last Login: 2010-08-12 17:32:24
Posts: 51, Visits: 600
Hi

I'm trying to create a custom ocl expression to see if an object is a parent in a hierarchical class.

So what I want to end up with is

Item.allInstances->select(i | i.Category.IsParentInTree('AssociationName', ParentCategoryObject))

In the OclOperationBase Evaluate method, how do I get a reference to the calling object, in this case the Category?

Thanks

Nick
Post #1451
Posted 2008-12-16 16:24:16
Forum Guru

Forum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum Guru

Group: Forum Members
Last Login: 2010-08-12 17:32:24
Posts: 51, Visits: 600
Hi

I've found the answer....I must put Alois's book in the car - or is there a PDF download?

The calling object is always passed as Parameter[0]

Nick

Post #1454
Posted 2008-12-16 16:25:01
Forum Guru

Forum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum Guru

Group: Forum Members
Last Login: 2010-08-12 17:32:24
Posts: 51, Visits: 600
Please could someone who has access, update the title to read Custom not Customer

Thanks

Nick

Post #1455
Posted 2008-12-16 16:40:58
Forum Member

Forum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum MemberForum Member

Group: Forum Members
Last Login: 2012-01-23 17:45:58
Posts: 49, Visits: 72
free download at http://www.lulu.com/content/2330695
Post #1456
Posted 2008-12-16 17:38:04
Forum Guru

Forum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum Guru

Group: Forum Members
Last Login: 2010-08-12 17:32:24
Posts: 51, Visits: 600
Thanks Alios

Downloading now......

Post #1458
Posted 2008-12-18 00:18:29
Forum Guru

Forum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum Guru

Group: Forum Members
Last Login: 2010-08-12 17:32:24
Posts: 51, Visits: 600
For those interested here is the end result

Assuming 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;

Post #1464
Posted 2008-12-18 00:33:06
Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

Group: Administrators
Last Login: 2010-11-30 12:17:13
Posts: 1 230, Visits: 1 382
Why does it have to be based in the Product class?

My alternative suggestion would be to define a derived association "allChildren" (0..*) from category to category that is defined recursively:

self->union(childcategories.allChildren)

it will contain a complete subtree including the root (so maybe "allChildren" is not the best name...). Then get the products with:

Category.objectfromExternalId(xxx).allChildren.Products

This way you don't have to load products that you don't want in the end result.


/Jonas Hogstrom [CapableObjects]
Post #1465
Posted 2008-12-18 01:07:45
Forum Guru

Forum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum GuruForum Guru

Group: Forum Members
Last Login: 2010-08-12 17:32:24
Posts: 51, Visits: 600
> Why does it have to be based in the Product class?

I'm building a dynamic search page with multiple search fields so I wanted to be able to start all my Ocl

Product.allInstances->select.....->select(.....->select(....


> My alternative suggestion would be to define a derived association "allChildren" (0..*) from category to category that is defined recursively:

I think I might use this, but I may do it with a custom Ocl function so I can call

Category.AllChildObjects('AssociationName').Products

This way I'm not relying on it being coded in the model.

If my user selects a category and another hierarchical association my Ocl could then be

Category.AllChildObjects('AssociationName').Products->Intersection(OtherHierarchicalClass.AllChildObjects('OtherAssociationName').Products)->select(Name.SqlLike(''''))

I hadn't noticed the "Intersection" function until now, so I couldn't see how to do the above without starting at the Product class and having chained selects.

> This way you don't have to load products that you don't want in the end result.

This would be much better.

Would there be any (much) performance difference between the Derived Association method and the Ocl function method?

Thanks for your help

Nick

Post #1466
Posted 2008-12-18 09:46:33
Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

Group: Administrators
Last Login: 2010-11-30 12:17:13
Posts: 1 230, Visits: 1 382
nickcrisp (2008-12-18)> This way you don't have to load products that you don't want in the end result.

This would be much better.

Would there be any (much)performance difference between the Derived Association method and the Ocl function method?


That depends on on how deep your hierarchies are, and how often they change. The derived association will cache its result between calls and only need to recalculate when the category structure changes, recalculating the whole list will be a linear operation, but that is probably not a problem since there is likely to be fewer categories than products anyway (so the linear factor of the products will always be greater than the linear factor of the categories).


/Jonas Hogstrom [CapableObjects]
Post #1467
« Prev Topic | Next Topic »


Reading This Topic Expand / Collapse
Active Users: 0 (0 guests, 0 members, 0 anonymous members)
No members currently viewing this topic.
Forum Moderators: HansKarlsen, Jonas Hogstrom, PeterMorris

Permissions Expand / Collapse

All times are GMT +1:00, Time now is 12:04

Powered By InstantForum.NET v4.1.4 © 2012
Execution: 0,266. 8 queries. Compression Disabled.