Hi,

Martin Marinschek napsal(a):
Hi Zdenek,

A question was raised about why state isn't retrieved from the
attributes map - this cannot be used, however, cause it would use
reflection internally and call the getter of the method, if a value is
not directly stored in the attributes map. As soon as the getter is
called, after the check for the local value returns null, you will get
back the value from a value-expression, and you do not want to save this
value in the state, as the value-expression itself is already stored!

so you want to get rid of the concept of a local value completely, and
store everything in the attribute map? Now I see. This might actually
work, yes.

1. getting rid of attributes' local values - yes,
2. getting rid of most getters/setters w/o special code in them (as typical use today)

2 should be possible with JSP tags, don't know about Facelets (maybe tag-handlers could do this)

From spec and API's JavaDoc i got this idea of processing attributes:

reading:
- check if special getter -> use it (if it looks at Map/VB is optional)
- check if in map -> use it
- check if value binded -> resolve and use it (or use default in some cases)

writing:
- check if special setter -> use it AND
- store in map

using in lifecycle's process:
- Restore view:
  - restore Map (done by ancester in API)
- Apply Request:
- resolve all ValueBindings and store them in Map to avoid multiple resolving
    - basically reading all attributes defined in tld and still not in Map
This should make this work for Mojarra's all getter/setter way (if "forgot" writing values into Map) - possible optimization could be in "lazy" fetching attributes when needed (once fetched, store in Map) To avoid saving these generated attributes' values, add/alter special key in Map (e.g. "o_a_m_generatedAttributes") with array containing names of those attributes
- next phases:
- use values from Map (if not lazily fetched already complete, adding new entries when not along with modifications of special key's value)
   - NOT using reading of attributes as above if already in Map
- writing attributes as above and if attribute's name present in special key's array, remove it from that array - any direct modifications w/o deletion in array (e.g. for internal processing) made in Map's values of generated attributes will be ignored in state saving
- Render Response:
 - clean Map of generated stuff:
     - remove all entries with null value
     - remove all entries with names in special key's array
     - remove special key
 - saving Map (done by ancester in API)

Having attributes both in Map and local properties (as of today and present in API) is not an obstruction - values in local properties take precedence,
because Map is stored/restored first.

Using this could possibly make any kind of generator for COMPONENT classes needless - all generic code for all attributes would be written once.

Only setters/getters i'd like to see in components' classes are with special behaviour code (but still using Map in the end).

Tasks in this approach:
- generating TAGS (JSP and Facelets)
- create utility class for
 a) getting values from Map to use in component's methods, e.g:
static public Boolean getBoolean(UIComponent comp, String attr, Boolean default) {
    Object res = comp.getAttributes().get(attr);
    if (obj != null) return (Boolean)res;
// check if in special key - it may got resolved to null -> return default // not in special key -> resolve it, add to Map (along with adding to special key's array)
    // resolved != null ? return (Boolean)resolved : default;
 }
 (I think default can be got from TLD for JSF 1.2)
 b) setting values to Map, e.g.
static public void setBoolean(UIComponent comp, String attr, Boolean value) {
   // if special setter, use it
    comp.getAttributes().put(attr, value);
    if (comp.getAttributesMap().get("o_a_m_generatedAttributes") != null) {
     // remove attr from array
   }
 }

This way it would be only in Tag class/TLD to define new attributes which would be automatically saved/restored. (This also fulfills JSF 1.1 spec in handling generic atributes from section 3.1.10)

OR (to be really on business of thread):

With this approach it would be pretty easy to support one method of generating libs: Annotations (or XDoclet) written for component class defining attributes - name, type, default value, target language, description... This annotation should inherit all definitions from component's parent class. - this way developer can really see which attributes he can really use in component's code AND
- the class is compilable on it's own (it's accessing already existing Map)


Regards,
 Zdenek
regards,

Martin


Reply via email to