Forum OpenACS Q&A: Categories in OpenACS 4

Posted by Jun Yamog on

What is the generic data model used in OpenACS 4 for a tree like
structure?  Basically I need to use this in somekind of a category.
Much like how site_nodes and cr_folders is.  Although I would not like
to use them since my module does not have anything to do with CR or
site nodes.  I dont want to develop my own datamodel since OpenACS 4
encourages you to use a shared data model.

I will probably need something like node_id, parent_id, name,
tree_sortkey <- I will do it in postgres.

Posted by Peter Alberer on

I do not think that there is a good table that you could use for something like categories (the acs keyword system is cr_items only i think) but you can easily use the tree_sortkey solution in other tables.

You just need to create a table with a node_id, a parent_id and a tree_sortkey column. (the columns you mentioned would be ok i think) Then you should assign triggers that generate the tree_sortkey on inserts and updates.

i am not sure how the functions have to be like, as the sortkey issue has changed some weeks ago but just check out the current versions of these functions for the cr_keyword table for example.

This is in /packages/acs-content-repository/sql/postgresql/content-create.sql, there you can find examples for relevant trigger functions and also have a look at the keyword system.

Posted by Jun Yamog on
Thanks Peter!

Wow the horror of facing the fact that there is no common tree data
model structure.  Doesn't ACS 3.x had this?  I think it was called
categories and it even had an admin interface.

Oh well should I decide do this stuff I think the best way to
implement it is.

acs-categories (or maybe acs-tree)

node_id, parent_id, package_id, order_id (?), tree_sortkey.

It will look like or the same with site-nodes but object_id is now
package_id.  I dont want to use site-nodes even though it does fix
my problem since my application does not have to do anything with
site nodes.  Unless some OpenACS guru tells me that you can use
site-nodes or use this table instead.

Posted by Don Baccus on
Yeah, use the tree_sortkey approach in PG, "connect by" in Oracle.

The PG triggers (written by Dan Wickstrom) can easily be replicated for any table, check out acs_objects or content_items or any other tree-oriented structure in the system for examples.

The current approach based on BIT VARYING is very efficient and makes full use of indexes.

I need to find time to properly document these, grrr ... at the moment your best bet is to read my comments in acs-kernel/sql/postgresql/postgres.sql and to look at examples.

Posted by Neophytos Demetriou on
There is a generic data model in the acs_objects table using context_id. IIRC, it was not used for categorization due to a warning of not attaching any semantics to it. Anyway, I agree that a new acs-categorization package would be wonderful to have. I have a simplified version of the acs-objects data model from my efforts to learn more about the tree_sortkey mechanism. [Note: Don, I have only changed context_id to "not null". This avoids the tests in the trigger functions and IIRC it improves performance since there no null values anymore. I use a root object_id=0 and then add the constraints]. Don, if you think this is a good idea I can email it to Jun and he could adopt/evolve it into the categorization data model.
Posted by C. R. Oldham on
I thought context_id was specifically for security and inheritance of permissions. (cf. ACS 4.0 Permissions Tediously Explained),
Posted by Neophytos Demetriou on
Yes, that's it. Note that I said evolve the simplified data model into a new categorization package so that Jun or anyone else who is going to work on this don't have to start from zero.
Posted by Dave Bauer on
How is this better or different than creating a new object_type and using acs_objects to create the category tree?
Posted by Neophytos Demetriou on
Dave, it's the same thing but instead of using the acs_objects table to represent the hierarchy you have a separate table (see post above about not using context_id with other semantics).
Posted by Don Baccus on
Yes, context_id is used for permissions inheritance, thus must be settable to NULL.  In fact defaults it to NULL.  This is key to the permissions model.  The distinction's blurred because there are packages that use context_id as a surrogate for "my parent" rather than "the object I inherit permissions from (if any)".  Such code is wrong and should get cleaned up someday.

The "proper" way to do that in the original ACS 4 design is to have a parent column in your derived type and use that to relate objects together.

Whether or not a general mechanism should be provided is worth thinking about, but adding to the existing breakage of the usage of context_id isn't the right way to go about it.

Posted by Jun Yamog on
So I guess there will be an acs-categories in the future together
with some helper db procs acs_categories__get_root, etc.  So I am
counting on Neophytos to put his code in.  In the meantime I will
make my own, its should be a good lesson for me.  Thanks for the
great feedback.
Posted by Malte Sussdorff on
If you want to have a quick fix which should be fairly easy to port, check the categories system of ACS 3.5, namely:
All in all not more than 1000 lines of code Example how this works:
Posted by Stephen . on
Some packages use context_id to denote 'my parent' AS WELL AS 'the object I inherit permission from', not INSTEAD of.  If your object always inherits permissions from it's logical parent then you can use context_id and there is no adverse interaction with the permission system.

I think this all got started because there was talk of a need for a general way to model containership, i.e. 'which is this objects parent', and an idea was to overload the context_id, as typically the logical parent is the object permissions should be inherited from.  If the core ACS assumed a logical heirarchy through context_id it would be impossible to create models with different security contexts and parents, hence the "don't overload context_id" argument, maybe...

I like Neophytos' not null improvement to the context_id column. A null context_id signifies 'default' only (whether permissions should be inherited is controlled by security_inherit_p), so he is inserting the default security context explicitly.  Does this even have implications for Oracle and it's inability to index null values..?

Posted by Neophytos Demetriou on
Hi everybody, I have posted a request for comments in the OpenACS Design forum about a new categorization package. The link is here:

Please take a minute to give us some feedback. Mark, I tried visit the link you provided but I get an error message. I have checked the acs35 datamodel though.

Posted by Neophytos Demetriou on
s/Mark/Malte :)