> -----Original Message-----
> The purpose of the DynaBean design (I'm not firmly attached
> to the name,
> but kinda like it :-) is to support application programming
> designs based
> on JavaBeans design patterns, but where the static nature of JavaBeans
> themselves (i.e. the fact that the set of properties is fixed
> at compile
> time) is too restrictive.  Some typical use cases for such a
> capability:
>
> * A bean object that represents a Row from a JDBC ResultSet
>   (the names and types of the column properties cannot be known
>   in advance because they are based on the SELECT statement).
>
> * A way to construct and use "value objects" that extract the
>   properties of an EJB into a structure that can be utilized by a
>   presentation tier technology such as JSP pages, without having
>   to hand code the value object.
>
> * A way to capture *all* of the request parameters from a servlet
>   request as a single object.
>
> * A way to dynamically represnt XML input data as a tree of
> Java objects.

>From this, it sounds like you're trying to build a "generic" object that
can be used to get the equivalent functionality of JDBC ResultSet (which
is already column agnostic), HttpServletRequest (encapsulates request
parameters, request headers, etc.), DOM (represents XML as a tree of
Java objects), etc.  In other words, rather than use an application
specific method for expressing dynamic data, you're looking to create a
generic, application-agnostic specific method for expressing data
unknown at compile time.  Does that summarize things?

If so, I would say that the APIs for the WBEM CIM (JSR 48) stuff aims to
do something similar.  For their current API, see:
http://wbemservices.sourceforge.net/javadoc/api/javax/wbem/cim/package-s
ummary.html
That API isn't final yet, pending JCP approval and all that.

The API uses a CIMClass to hold the definition of a "class" and a
CIMInstance to hold an object instance.  An object instance has
properties which are retrieved using the getProperty method.  The
property (a CIMProperty object) has the property name, its type, and its
value, along with various qualifiers.  The type is represented as a
CIMType, and the value is represented as a CIMValue.  The CIMValue has
the ability to determine whether the value is null, is an array, what
its type is, and what the underlying value is.

The CIMInstance is very similar to a "value" object as you describe in a
later email.  You can make whatever modifications to it before passing
it back to the instance store for persistence or something like that.

One thing CIM also supports are methods.  Although you seem more
interested in storing values, so this probably isn't as relevant.

I work with the CIM apis at my day job, and I can't say they're the
designed the best (the use of Vector everywhere makes me cringe), so I'm
not advocating the direct application of the APIs for the projet you are
proposing.  There just might be a couple of things to learn from their
work so far.  Anyway....

> DESIGN REQUIREMENTS:
>
> * Support a completely arbitrary set of properties and corresponding
>   values, with the ability to add and remove properties dynamically.
>
> * Support the ability to dynamically register the set of property
>   names that are allowed, and then enforce storing only those
>   property names.
>
> * Support the ability to register data types (Java classes) for each
>   property, along with the names, with automatic type checking.
>
> * Support for properties with scalar types, array types, and
>   "mapped" types (as currently supported in Beanutils).
>
> * Support "simple" and "indexed" property getters and setters
>   in a style similar to standard JavaBeans.
>
> * Support registration of property change listeners and broadcast
>   of property change events

This is something I don't think CIM has, and I think is sorely needed.
Does this design requirement include vetoable change capability as well?

> * Provide the basic DynaBean API as a Java interface, as well as a
>   convenience base class, so that applications can adopt it however
>   they wish.
>
> * Base implementation class should implement Serializable so that
>   DynaBeans can be serialized and deserialized (assuming that the
>   actual property values can be).
>
> * Transparently support DynaBean objects in the existing BeanUtils
>   and PropertyUtils classes of the Bean Utilities package.
>
> * To the maximum extent feasible, provide JavaBeans-like introspection
>   capabilities of the available properties.  May require an
>   IntrospectionUtils addition to the Beanutils package.
>
>
> CONCEPTUAL API:
>
> public interface DynaBean {
>
>
>     //
> ----------------------------------------------------------------
>     // Dynamic property configuration
>     //
> ----------------------------------------------------------------
>
>     void addDynamic(String name);             // Unrestricted type
>     void addDynamic(String name, Class type); // Restricted type
>     void removeDyanamic(String name);         // Remove
> property & value
>     void restrictDynamic(boolean restrict);   // Are property names
>                                               // restricted
> to registered
>                                               // ones?
> (default=false)
>                                               // (can be changed)
>
>     //
> ----------------------------------------------------------------
>     // Property getters and setters.  Behavior on previously
>     // unknown property names depends on the restrict setting
>     //
> ----------------------------------------------------------------
>
>     // Does this bean have a property of the specified name?
>     boolean contains(String name);
>
>     // Getters return null on unknown property names
>     Object get(String name);                  // Simple
>     Object get(String name, int index);       // Indexed
>     Object get(String name, String key);      // Mapped
>
>     // Setters are allowed to set null unless property is native.
>     // Optionally throw IllegalArgumentException if type is restricted
>     // and the value argument is not assignment-compatible
>     void set(String name, Object value);      // Simple
>
>     void set(String name, int index,          // Indexed
>              Object value);
>     void set(String name, String key,         // Mapped
>
> }

I think you missed an "Object value);" after the set for mapped
properties.  :)


I'm not sure that having the typing information (i.e. the *Dynamic
methods) in the same class is going to give you the best runtime typing
information.  You can verify the properties are the proper types, but
there's no way to verify the bean conforms to a particular set of
properties without checking for the existance and type of each of the
properties.  Plus, the typing information would be duplicated for each
DynaBean instance.

Consider moving the property definition stuff out to a separate
interface, say "DynaClass".  Then, you can create a DynaClass, specify
the properties on the class, use the class to create any number
instances where values are assigned to the properties, keeping the
typing information in the DynaClass rather than the DynaBean.  The
DynaBean doesn't necessarily need to conform strictly to the DynaClass
(you could add properties that aren't defined in the DynaClass), and you
could modify the DynaClass dynamically as well.

This way, you get the ability to reduce the memory footprint by keeping
typing information in the class that's reused rather than in each
instance.  Plus, it also gives you the ability to define validation
methods or something like that which can be used to ensure all the
defined values have been set appropriately or whatnot.  Although I'm not
all that familiar with Struts, I can see how the DynaClass would be
anologous to the ActionForm class definition, and the DynaBean would
actually hold the actual form data.  One form definition (DynaClass),
multiple users providing data (DynaBeans).


You mention restricting setting properties to null if the property is
native, but I think there's a little bit more that can be done with
that, especially since you only have support for "Object" (in which
case, there's no easy way to distinguish between primitive and other
objects).

Consider accepting "qualifiers" when the dynamic property is added.  One
qualifier could be the java Class that the value must be an instance of.
Another would be whether a "null" value is acceptable.  You could also
extend this to an "enumeration" qualifier (e.g. property "Status" can
only have the values "Stopped", "Starting", "Running", and "Stopping").
A generic qualifier API could be created such that more complicated type
validation could be added (e.g. a regular expression qualifier to ensure
a string property value has an appropriate form).  Such a generic
mechanism may lead to someone building "logic" into the qualifiers
rather than "type" information.

I'd be more than happy to put these thoughts into an API if it might
help explain the ideas I've expressed.

> Craig McClanahan

michael



--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to