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: [status/roadmap] JXTG Refactoring
Date Mon, 24 Jan 2005 20:44:50 GMT
Leszek Gawron wrote:
> Daniel Fagerstrom wrote:
> 
>> The remaining problem for removing references to the JXTG instructions 
>> from the Parser is that StartDefine have a finish method that is 
>> executed when its end tag is reached during compilation. finish() take 
>> care of installing the parameters within jx:definition.
>>
>> There are two possibilities for making StartDefine being compiled in 
>> the same way as the other instructions.
>>
>> 1. Let the parameters install them selves in StartDefine as when and 
>> otherwise do for choose.
> 
> I do not like it. Every tag that would require jx:parameter would have 
> to implement two classes: one that handles the tag itself and the second 
> one for the paramter:
> 
> jx:macro name="macroName"/jx:paramter name="foo" defaultValue="bar"
> 
> jx:call/jx:paramter name="foo" value="bar"

They could implement some ParametrizableInstruction interface that they 
can install there seves through. Still I don't like it either. I 
suggested it as it requires less changes of the current architecture.

>> 2. Refactor the instructions so that they are constructed at the end 
>> tag instead of the start tag. This require more work as the 
>> instruction extends the start tag and must be made an own object that 
>> is refered to from the start tag instead. Also instead of that tags 
>> has access to the stack of parents it would have access to its 
>> compiled children.
> 
> This one is better but still there are some cons. If every tag is to be 
> meant final then there are 2 objects for each tag instead of one. The 
> script size doubles.

No it doesn't the "instruction event" tag just contains the start and 
end locations, maybe name and attribute and a referece to the 
instruction object that contains the instruction data. So the data will 
be splitted in two objects instead of one. The script will be a little 
bit larger but script size is anyway not a particulary important aspect. 
Caches and such things will contain most of the runtime data anyway.


> I like Jonas' approach. Create the tag at startup but do the work at 
> finish (on the same object). Still this does not allow for final objects.

We can create the "instruction event" tag at startup and the instruction 
  object at finish.

>> I would prefer 2. even if it requires more work as it among other 
>> things means that all member variables can be final as everything is 
>> constructed as once.
> 
> Why are you pushing for final variables in this case? I do not see much 
> gain here.

Its maybe not that important. The gain is that if you have all 
instruction member data final you don't risk to write code that changes 
them by mistake which you wnat to avoid as they must be thread safe. It 
is also possible that the compiler can make some use of that they are 
final, I don't know.

Another reason that I want to separate the instruction event from the 
instruction object is that it will be easier to reuse the instruction 
object when we write an attribute template language, if they not are 
connected to an element.

Anyway we go for some variant of solution 2.

>> Once this is solved we can refactor the Parser so that it take a 
>> exprssion factory, a string template parser and a set of instuctions 
>> as arguments and remove all the references to specific instructions.
> 
> There is one big thing asked many times for: jx:attribute 
> implementation. AFAIU the implementation is not that trivial at all:
> <foo>
>   <jx:attribute name="fooattr" value="barattr"/>
> </foo>
> 
> This is the most simple case. Still you have to cache all ignorable 
> whitespace awaiting possible jx:attribute. This may affect performance 
> and raise memory allocation per script invocation.

Hmm, can't we just throw away the ignorable whitespaces between the 
start element and the jx:attribute?

> <foo>
>   some content
>   <jx:attribute name="fooattr" value="barattr"/>
> </foo>
> 
> Is it ok to generate some text content and request jx:attribute later 
> on?

I don't think we should allow that, it doesn't make sense as the 
attribute refers to the element and not the text.

> I do not quite remember how it is handled by XSLT

It is forbidden there, http://www.w3.org/TR/xslt#creating-attributes.

> <foo>
>   <jx:if test="${doAttributize}">
>     <jx:attribute name="fooattr" value="barattr"/>
>   </jx:if>
> </foo>
> 
> Get's even better if you involve instructions.

Ok, thats tricky indeed. I bet the XSLT designers had DOM tree building 
rather than SAX emitation when they designed that instruction :/

> It looks like all content no SAX event may be generated until we are 
> sure there can be no jx:attribute, which means another node is being 
> started or the current one gets finished.

Yes, thats my interpretation also.

> This may not be that hard to implement

I'm afraid that it is hard to implement. I see two possible solutions:

1. Compile time analysis: For each element there is one list of 
attribute generating instructions and one list of content generating 
instructions. All instructions and events are classified as attribute 
generating, content generating or unspecified (e.g. jx:if). An 
unspecified gets its type from its childs (throgh bottom up 
propagation). The complicated thing with this scheme is to type check 
the macros, which means that all macros much be gathered during compile 
time.

2. Run time handling: As you suggest above, the problem with this is 
that it doesn't fit well with the SAX content handler. We need some 
extended content handler that allows for attribute events as well, and 
not sends a start element event until the next text element, start or 
end element is recieved, so that it knows that all attributes are consumed.

> but I'd rather go first with 
> event code refactoring and just keep that feature in mind so the 
> architecture allows for future implementation.

Yes.

>>
>> Execution
>> - - - - -
>>
>> Each instruction has an execute method that is called in the Invoker:
>>
>> public Event execute(final XMLConsumer consumer,
>>                      ExpressionContext expressionContext,
>>                      ExecutionContext executionContext,
>>                      StartElement macroCall,
>>                      Event startEvent, Event endEvent)
>>     throws SAXException;
>>
>> Here consumer, expressionContext and executionContext is rather 
>> obvious.  Of the remaining arguments we have macroCall that is used to 
>> pass the macro call body that can be executed whithin a  macro with 
>> jx:evalBody. For getting things simpler I would suggest that parameter 
>> to be removed and passed in the expressionContext instead, this is 
>> already done for an ordinary macro call that puts the information in 
>> the variable macro. This should be done for jx:eval as well.
> 
> Agreed. Out of over a dozen cases the macroCall is not null only once or 
> twice. Awful :)

Actually it is non null in more cases, if you have a number of jx:if, 
jx:forEach or jx:choose that encloses the jx:evalBody e.g. But this can 
be handled with the macro stack parameter anyway.

>> One could refactor the events so that we get a more tree based design 
>> as in Jonas proposal. it is easier to write code for that than the 
>> startEvent, endEvent representation in JXTG. But I don't know if it is 
>> worthwhile.
> 
> Do you mean that every event is represented only for one class which 
> remembers the exact start and finish position in compiled script?

Yes

> I like 
> it much more that current JXTG design but it is in contradiction with 
> your requirement that every Script event should be final.

Not necesarilly as described above.

>> We could simplify the invoker by puting the sax generating code in 
>> execute methods in the events also, but thats mainly cosmetic.
>>
>> I would like to break out the macro execution code from the Invoker 
>> but it needs further research to see if it is possible.
>>
>> Import
>> - - -
>>
>> The import instruction performes the import in during execution I 
>> would much prefer to do it during compile time. Is that possible 
>> without breaking current functionality?
> 
> I haven't checked the code but can you do jx:import 
> uri="${bizData.somePage}"/> or not?

That is allowed which rules out compile time import. I don't understand 
the reason for that instruction, Chris Oliver seem to be obsessed with 
efficency in most other cases.

XSLT manage without dynamic URI parameters in xsl:include and 
xsl:import, and I think we would as well. I sugest that we implement a 
non dynamic jx:include that can be performed at compile time and start a 
vote about deprecating jx:import when we have finished that.

/Daniel

Mime
View raw message