[Seaside] components via meta-data?

itsme213 itsme213 at hotmail.com
Sat Jul 1 21:00:55 UTC 2006


Apologies for this long post from a newbie. I was trying out Adrian 
Lienhard's Mewa with Seaside and it seems Mewa has languished. I was curious 
what knowledgable Seasiders thought of the following.

QUESTION: Can we build very smart Seaside components automatically from 
meta-data of the domain objects, and still require a very small amount of 
meta-data for customized components?

What's different about these "Components"?
=========================================

Nothing changes on the interface between the Component and sessions, 
browsers, etc. However, each component in that tree is connected to domain 
objects via a meta-layer. This meta-layer provides a uniform (structural) 
reflective interface to all domain objects, their attribute values, and 
their operations including parameters and calling constraints, so that 
generic view and editor components can operate through this interface.

What is this meta-layer?
========================

Components in successive levels of the component tree are (STRICTLY) 
attached to either
  - (meta)objects or
  - (meta)attributes of those object, or
  - (meta)operations on those objects

A meta-object (in this discussion) is NOT a class; rather, it is a 
proxy-like object carrying meta-information for a specific domain object 
(instance). (The "meta" terminology comes from Mewa).

A meta-attribute is an object carrying meta-information for the value of a 
specific attribute of a specific object.

A meta-operation is an object carrying meta-information for a specific 
operation that might be invoked on a specific object.

In combination these three carry all the information needed to construct 
components.

The attached pictures from the Mewa paper show the essential idea (but don't 
include the meta-attributes and meta-operations).

None of these meta-things need db-level persistance, they might use 
session-level persistence. Below is pseudo-Ruby code (sorry, I am not yet 
fluent in Smalltalk):

class MetaObject
  # mostly acts as a proxy to obj, adding meta-information
  has_one :obj, Object
  has_many :attributes, MetaAttribute
  has_many :operations, MetaOperation
  def renderHtmlOn: html
    # walk attributes to structure views
    # walk operations to structure buttons/anchors/editors/...even wizards
  end
end

class MetaAttribute
  # a slot value of a domain object i.e. obj + attr + value
  # or, a slot + value of an operation on an object (op + param + value)
  has_one :attribute, Symbol
  has_one :type, Class # or duck-type
  has_one :multiplicity, Symbol
    # :attribute, :type, :mult should be shared via class level Attribute
    # I've just stuffed them here, just easier to understand this way

  has_one :owner, Object # domain obj or a MetaOperation (below)

  def value
    owner.instance_variable_get attribute # or #send...
  end
  def replace (replacement_obj)
    # illustrative only
    owner.send "#{attribute.to_s}=", replacement_obj
  end
  def add (added_obj)
    # illustrative; only defined if attr is a collection
    owner.send "add_to_#{attribute.to_s}", added_obj
  end
end

class MetaOperation
  # an operation-to-be-called on an object
  #
  has_one :operation, Symbol
  has_many :params, MetaAttribute
    # tracks param name, type, multiplicity, etc.
    # Used to populate (d)html accordingly
    # including using the smarts below
    # :operation and :params could be shared via class level Operation

  has_one :owner, Object

  has_many :current_values, Hash
    # current user-selected param values, hashed by param_symbol

  # for populating of parameter candidates e.g. a drop-down list
  #   may be used via Ajax, including current parameter selection
  def candidates_for (param)
    owner.candidates_for operation, param, curr_values
  end

  # for enabling of operations e.g. menu or button enabling
  #   may be used via Ajax, including current parameter selection
  def invocable?
    owner.invocable? (operation, current_values)
  end

  def invoke
    owner.send operations, current_values
  end

end

Example meta-layer instance
===========================

Assume there is a component tree consisting of nested viewers and editors.

On demand, build metadata about domain objects that these viewers and 
editors connect to, including the attributes and relations of these domain
objects. Make that metadata structure uniformly as follows:
  m_obj
    m_attr
      m_obj
      m_obj
    m_attr...
    m_op1
      m_attr...
      m_attr...
    m_op2

So if I have objects
  joe=Person.new
  joe.name = "Joe"
  home=House.new(:address=>"123 hometown")
  joe.add_house home
  vacation_home = House.new
  joe.add_house vacation_home
  room1 = Room.new
  room2 = Room.new
  home.add_room room1
  home.add_room room2

  bob=Person.new
  joe.add_friend bob

Then a view or editor *on joe* will create and use this metadata structure:

  joe -- meta-object
    joe#name -- meta-attribute
    joe#name= -- meta-operation
    joe#houses -- meta-attribute
      home -- meta-object
        home#address -- meta-attribute
          "123 hometown" -- metaobject, optimized away
        home#rooms -- meta-attribute
          room1 -- meta-object
          room2
      vacation_home
    joe#friends
      bob


Example Component Tree
======================

CLAIM: The component tree should exactly parallel this metaobject and 
metaattribute structure (by default). So here are the components in that
tree, and the (meta)-things they connect to:

person_viewer --> joe
  #houses_viewer --> joe#houses
    house_viewer --> home
      #address_viewer --> home#address
        address_viewer --> "123 hometown"
      #rooms_viewer --> home#rooms

        room_viewer --> room1

        room_editor --> room2#modify
           new_size --> room2#modify.new_size

    house_viewer --> vacation_home
  #friends_viewer --> joe#friends
    person_viewer --> bob

As always, some of the elements in the above tree might change dynamically 
with Ajax e.g. a viewer might be replaced by an editor when the little 
"edit" link is clicked; but the editor would still be attached to the same 
meta-instance.

I believe all the components in this tree could be generic by default, all 
the meta-objects constructed automatically given a few meta-data hints.

Not sure how Seaside deals with Ajax right now, but we might need some event 
machinery between the tree and domain objects so an (Ajax) operation that 
replaced one component might also update other parts of related components 
in the tree. Ajax-induced updates would propagate up to the tree root 
collecting component updates, before going back to the client.

CSS
===

Seaside components can be reused wonderfully, including embedding them in 
others. But if CSS is only provided at the page level, would it make sense 
for a component to (somehow) compose the CSS of its parts? We could 
eliminate some CSS warts while at it 
http://lunchroom.lunchboxsoftware.com/articles/2005/08/19/rcss-anyone, and 
with a few restrictions still retain client caching etc. Far less important 
than the component ideas above, though.


Thoughts? Am I talking nonsense?

Thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mewa.png
Type: image/png
Size: 7139 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/seaside/attachments/20060701/c38a50a7/mewa-0001.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mewa2.png
Type: image/png
Size: 11481 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/seaside/attachments/20060701/c38a50a7/mewa2-0001.png


More information about the Seaside mailing list