Forum OpenACS Development: Container Object Proposal (or storing objects in objects)

Container Object

The container object allows storing more than one data element per attribute in an object. To use the container set the datatype in acs_attributes to the object_type to be stored. The value stored in the attribute is a container object. This provides a pointer to the contained objects and provides a generic mechanism for creating a hierarchy of objects.

Implementation
The container object_type keeps the information about where the container is contained. The subclasses keep track of what is contained. The first implementation will be a list container that allows storing lists of objects, numbers, strings and dates in an attribute. The length of the list is controlled by min_n_values and max_n_values in acs_attributes. The table structure consists of

table container (
	container_id references acs_objects(object_id)
	parent_id references acs_objects(object_id)
	attribute_id references acs_attributes(attribute_id)
)

table container_list (
	container_list_id references container(container_id)
)

table container_list_map (
	container_list_id  references container_list(container_list_id)
	sort_order  default container_list_map_seq.next_val
	object_id references acs_objects(object_id)
	number number
	date date
	string varchar(100)

	primary key container_list_id, sort_order
)
Notes: The container will support updating the sort order and still function correctly (sort order must be a positive number because deleted items will have a negative sort_order). This deleted 'flag' allows the container to run in garbage collect mode. This allows quick deletion of large number of objects with a scheduled task to clean up the mess. The object_id, number, string and date columns store the typed data. If data larger than varchar(100) needs to be stored it's best to create an object_type like big_string. This keeps the containter_list_map column width reasonable.

Also adding a key column in a similar table would create an TCL array type container.

Methods

SQL
container_list.new() create a new container list object

container_list.get_attribute(object_id,attribute_name) will return a TCL list of values
container_list.del_item(object__id,attribute_name,sort_order) will delete the value stored at sort order

container_list.lappend(object_id,attribute_name,value) 
other TCL list functions such as linsert may follow

TCL

container::container_p object_id returns true if object is a container
container_list::get object_id attribute_name returns the result of container_list.get_attribute

The following will be implemented in a later release. 
container::get_schema object_type returns an xml schema for the object_type
container:;get_xml object_id returns an XML document for the object
container::insert_xml object_type xml returns object_id and inserts XML into that object
These functions will allow exporting data from one ACS install and importing it into another without object_id problems. 
Core Changes None required, but I might be nice to make a storage_types table and make a foreign key to acs_attributes.storage. That combined with modifying get and set attribute would allow storing typed data in a generic way. It would also allow other types of storage such as XML and CMS. Future improvements could be get_xpath_attribute and set_xpath_attribute.

Comments?

Barry,

Have you looked at cr_child_rels and the way the content repository models child objects?

Would this meet your requirements? I was thinking that this could be pushed out to the acs_object level. I do like the idea of merging the relationships into the acs_attributes system so that the type of child relationships are available to the attribute system, which then could be used to render forms.

The container class is really a combination of two things I wrote before. I needed a generic storage type that could be indexed and the acs model only stored varchar(4000). Allowing multiple rows per attribute makes the model more flexible. Another feature (or not) is the data can be type checked. The cr_child_rels looks like it can link any object with any other object, perhaps without the parent having prior knowledge of this. The is very useful also but not really the same thing. For example the container model will allow building an XML schema from the matadata because the hierarchy is known at create time, the relations in the cr_child_rels can change dynamically.
It sounds useful, Barry. But we should really look closely at the content repository -- a lot of work has gone into it, and even though it takes a long time to figure out what it's doing, perhaps we should improve or extend that rather than adding in a whole new method of doing things?
As Barry says, the two don't really solve the same problem...