cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Fagerstrom <dani...@nada.kth.se>
Subject Re: [RT] Attribute Rendering and CForms Convertors
Date Thu, 04 Nov 2004 22:42:40 GMT
Jonas Ekstedt wrote:
> On Wed, 2004-11-03 at 21:46 +0100, Daniel Fagerstrom wrote:
<snip/>
>>In some cases like when you 
>>can build lists or trees in the user interface, a more traversal based 
>>interface is needed.
> 
> I agree that I haven't really thought this issue through thoroughly. In
> the widget framework there is a "public int size(String path)" method
> that returns the size of whatever object is present at that path. But
> there could certainly be more stuff thrown in such as support for
> pointers similar to JXPath that can run around in your model data.

Yes, a tree traversal inteface is needed maybe something like:

   String getValue(String path);
   Pointer getPointer(String path);
   Iterator getIterator(String path);

>>Also, like everyone else that has commented your proposal, I think that 
>>it often is a bad idea to write directly to your model. Even if you are 
>>able to solve the security problems, the model will still need to be 
>>able to store partially invalid input data and missing data. IMO it is 
>>better SoC to have a form model in front of the real model. This 
>>decreases the complexity of the model as it always can get data in a 
>>more transactinal way in complete chunks.
> 
> Protecting the application object is partly what the Model interface is
> all about. In the getValue/setValue functions you can implement any
> measures to protect the application object you'd like. The point is that
> the user should decide what type of shielding should be used. 
> 
> Eg. the project I'm working on is dependant on letting the view access
> derived values from the bean model. That means I need to populate the
> beans directly. I do not really care if the beans are inconsistent as I
> won't hibernate them if they are (in a sense the database is my
> "application object" that I need to shield). So in my case it makes
> sense to operate directly on the application object.
> 
> However, as a different example, should I start using beans with
> properties like ints or Dates then I would choose some other strategy as
> I need to be able to save values even when they are not convertible. In
> this case the wrapping model could store illegal values in a separate
> map. getValue() would then return values from the map if they exist or
> from the bean otherwise.
> 
> The second approach is similar to how CForm widgets works. What I think
> is the benefit of the Model interface is that it is up to the user to
> decide what type of shielding should take place.

I agree that CForms is a little bit monolitic and that it would be god 
if we could find a strict decomposition of the different involved 
concern areas. Then we could have well defined and hopefully small 
interfaces between the parts and make it possible for webapp developers 
to reuse parts of it.

My curent view of the involved concern areas is something like:

+------------------+    +-----------+    +-------+    +----------+
| RequestProcessor |--->| Convertor |    | Form  |    | Business |
+------------------+    +-----------+<-->|       |<-->|          |
| Template Engine  |<---| Renderer  |    | Model |    | Model    |
+------------------+    +-----------+    +-------+    +----------+

Of course there is a controller as well, but that is not the subject for 
this discussion. Compared to the usuall MVC pattern we can see that the 
model is split in a form model and a business model. The binding step 
between the form and business model should maybe also have an own box, 
but then the image didn't fit within the 71 charachters ;). We also have 
a convertor/renderer step. Compared to CForms curent state the request 
processor, and convertor/renderer has different positions.

We folow the data from request to respons. The request processor parses 
the request object or the xml input or what you have. And write this to 
something like the model interface you proposed:

   void setValue(String path, String value) {
     Datatype type = formModel.getDatatype(path);
     Object obj = convertor.convert(value, type, locale);
     formModel.setValue(path, obj);
   }

We could maybe call this part a view adapter. It doesn't contain any 
data and is only an adapter that perform the conversion/rendering before 
writing to/reading from the form model.

For the form model <-> business model communication everything is like 
it use to be. With the adition that for some kinds of business model 
implementations, like DOM-trees, XML DBs and RDBs, it might be usefull 
with a convertor/renderer step also. So that you don't have to use the 
same data type conversions in the binding each time you use a certain 
data type.

In the last step the template engine reads from the view adapter thru a 
tree based interface, like the one I proposed in the begining.

So in this model the view adapter gives read and write access to an 
untyped tree and the form model is  a typed tree that also contain 
validation and event handling.

                             ---o0o---

Given that we can find good interfaces between the different steps. You 
and other Cocoon webap developers can resuse parts of the form framework 
to your own liking. If you don't want the split in business and form 
model in a certain application you can still use the rest of the framework.

>>I prefer the request processor idea to the current form population where 
>>each widget reads it data from the request object. The current scheme 
>>makes CForms unecesarily bound to the request parameter model of input 
>>data. With a request processor that is reponsible to write input data 
>>into the form model, it would be easy to plug in a different request 
>>processor if one gets xml input from a browser that implements XForms, e.g.
>  
> I think it would be quite easy to make this change to CForm.

So do I, although I havn't studied the details in CForms for a while. I 
guess it can be done in a completely back compatible way. A request 
processor, a convertor/renderer and a view adapter needs to be written. 
Then one just don't use the readFromRequest and generateSaxfragment any 
more. There might be subtilities in the state sequence within widgets 
that complicates thins though.

WD[Y|O]T

/Daniel

Mime
View raw message