> -----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]>