Re: validateChildNode prevents extensions.
I see. Thanks for the explanation. Glen --- Finn Bock [EMAIL PROTECTED] wrote: BTW, without divulging too much that may hurt your interests, would you mind explaining your reluctance to just modify FOP source (replace classes, etc.) for what you are trying to market? Is it licensing issues--or is it more for programmatic style/user convenience? I want to better understand your reluctance on this matter. Legally the seperation between FOP and extension have placed a solid wall between my opensource fop-dev work and my commercial extension. My client cant claim ownership of any of the fop-dev work since the extension didn't require *any* changes to fop. Commercially, trying to sell an fork of FOP in order to sell an extension to FOP will never fly. regards, finn
Re: validateChildNode prevents extensions.
[Glen] Oh, when I meant alter the system I also meant adding classes, using different classes, etc., i.e., some things need to be done beforehand to accomodate a new element. Come on! That leaves alter the system without any meaning. Recompiling modified sources into a new fop.jar would IMO mean alter the system. Here is how extensions should work: http://xml.apache.org/fop/dev/extensions.html and that is effectively what I have done. BTW, without divulging too much that may hurt your interests, would you mind explaining your reluctance to just modify FOP source (replace classes, etc.) for what you are trying to market? Is it licensing issues--or is it more for programmatic style/user convenience? I want to better understand your reluctance on this matter. Legally the seperation between FOP and extension have placed a solid wall between my opensource fop-dev work and my commercial extension. My client cant claim ownership of any of the fop-dev work since the extension didn't require *any* changes to fop. Commercially, trying to sell an fork of FOP in order to sell an extension to FOP will never fly. regards, finn
Re: validateChildNode prevents extensions.
Extension writers has to create a subclass of AbstractLayoutManager (I just use a LeafNodeLayoutManager) and an subclass of Area. But that are normal operations since there are subclasses of those for each element type. I must also add code to the renderer to handle my area, but that is because the renderer code is not flexable enough to handle unknown area classes. I get around that limitation by plugging in a completely new PDF renderer. [Glen] OK, in other words, you have to change FOP source code to add a new XSL-based extension element. You have no problem philosophically with this. I was unclear. When I write an extension, I make *no* change to any existing FOP source files. And I do not replace any existing FOP class files with new version. For an extension element I have to writte a new version of FO classes, a layout managers, an area and also a new PDF renderer but these are all new files with new class names. Also, I can't replace the Block class with my subclass in the FOElementMapping without changing FOP sources. OK, you're saying again that you have to change the FOP source code in order to add a new XSL-based extension element, but now you're having a problem with adding *this* code. I don't want to change any FOP code! And if I have to change any FOP sources to add an extension, then FOP doesn't support extension with the meaning of extension as I understand it. I'm still not sure why this is causing you so much more consternation--isn't this trivial (even if annoying) to what you will need to do in the other classes? An extension mechanism where I can put an unmodified fop.jar and myextension.jar on the CLASSPATH and have it work is a defining issue to me. It is the mechanism that is currently paying my rent. Between changing code in 3 places with no validation for the user community (and tons of NPE/CCE complaints due to badly written FO's for the committers to deal with on the various lists), vs. changing the code in 4 or 5 places *with* validation for the user community (and few if any NPE/CCE complaints), you do have a bit of a tough case to make that the former would win a cost-benefit analysis. Having to subclass the parents will prevent two different unrelated extension from both having fo:block's as parents. Not true--fo:block already allows 20 or so different types of children--all distinct from each other. (But to further simplify your coding, all you have to do is check that the namespace URI is www.finn.com or whatever and you can choose to allow everything from that namespace.) I meant that if I have to either subclass or change Block.java then two independently developed extensions can not both be used in the same document. Remember, FOP is basically a compiler--like javac, you have to define its syntax it will accept, and that will require coding. Also, the only difference between an XSL FO and an extension FO is that the latter hasn't been blessed by the W3C yet. Both need validation and coding. I don't mind having to write validation code, but I seriously mind having to write it in exsting FOP sources. It has worked quite well before. Without changing any of FOPs layout or area sources. True. But in the old version, FOP would happily accept, say, an fo:root as a child of an fo:block, or an fo:layout-master-set as a child of an fo:list-item, and subsequently NPE while processing. That model simply had to change. Nobody would respect/use a product that operates that way, or a product based on such a product. Fine, but that can never be an argument for removing support for independant extensions. I mean exactly that the validation should be loose. If I need a finnbock:foobar tag as a child of fo:block, fo:block should not prevent me from doing so. Yes it should, if fo:block is to be XSL compliant. The Recommendation defines the content model (i.e., the children) that fo:block is to follow and their ordering. We modify that for the extension elements predefined within FOP--as we're allowed to. Then I, as an extension writer, also want to change the validation but without having to modify existing FOP sources. So the validation have to somehow be made plugable. Perhaps the extension elements can implement a tag interface to indicate that the extension shouldn't be validated by the parent. Or parhaps the checking could be disabled entirely. Actually, we could do that--fairly simple--let's see what the other committers have to say. We can add a boolean to FOUserAgent called disableValidation, have FOTreeBuilder read it every time it sees an FO in the stream, and on the basis of that decide whether or not to call vCN(). I see two problems though: (1) performance issue--this boolean will need to be read for *every* node in the FO document, I would guess that a check on a boolean for each node is a bit faster than calling vCN for each node. But I have not measured it. (2) FOP will be raising NPE and CCE errors for
Re: validateChildNode prevents extensions.
Finn Bock wrote: An extension mechanism where I can put an unmodified fop.jar and myextension.jar on the CLASSPATH and have it work is a defining issue to me. That's how it should work. The code build into the FOP core should only validate elements from the fo namespace and attributes from no namespace, and call validation for elements and attributes from other namespaces in roder to give them a chance to validate themselves. J.Pietschmann
Re: validateChildNode prevents extensions.
--- Finn Bock [EMAIL PROTECTED] wrote: I don't want to change any FOP code! And if I have to change any FOP sources to add an extension, then FOP doesn't support extension with the meaning of extension as I understand it. From what I understand a program may not change its own source code while it is running so we may not have complete freedom for everything. An extension mechanism where I can put an unmodified fop.jar and myextension.jar on the CLASSPATH and have it work is a defining issue to me. OK, this looks like a nice feature to have, and the modifications made to FOP in this regard can be helpful to others who have similar work to do. Here's what I see: Option #1: 1.) myextension.jar will need a FOElementMapping [1] subclass that will reroute fo:Block from Block.java to FinnBlock.java. Have FinnBlock.java override the vCN() for the new validation rules. (FinnBlock.java can also override addLayoutManager() if it uses a different one--let's discuss this one if it is an adequate substitute for your need for the LM makers we were discussing earlier.) Ideally, myextension.FinnFOElementMapping can subclass FOElementMapping so you will only need to define makers for the elements you are changing. 2.) FOUserAgent.addElementMapping() [2] is the interface to add an element mapping to runtime FOP. Embedded users wanting to link in your library in their code will need to call foUserAgent.addElementMapping(myextension.fo.FinnFOElementMapping); 3.) FOTreeBuilder currently loads the default mappers first, then checks for any user-added ones [3]. We will need to change this logic to have FOP first load any user-defined (or run-time discovered) element mappings first, then load each of the default ones *if* its namespace hasn't already been loaded. So for the user adding FinnFOElementMapping with the XSL namespace URI, this will result in FOElementMapping *not* being loaded, because it has the same namespace URI. 4.) (If applicable) Finally, for command-line users, subclass apps.Fop java, changing both constructors to load your element mapping: foUserAgent.addElementMapping(FinnFOElementMapping), and provide a finnfop.bat/.sh that will call this. Option #2: 1.) Same as #1 above. 2.) Provide a subclass of FOTreeBuilder in my extension.java that overrides the method setupDefaultMapping() to load FinnFOElementMapping instead of FOElementMapping. 3.) Same as #4 above. Thoughts? Glen [1] http://cvs.apache.org/viewcvs.cgi/xml-fop/src/java/org/apache/fop/fo/FOElementMapping.java?rev=1.8view=auto [2] http://cvs.apache.org/viewcvs.cgi/xml-fop/src/java/org/apache/fop/apps/FOUserAgent.java?annotate=1.15#112 [3] http://cvs.apache.org/viewcvs.cgi/xml-fop/src/java/org/apache/fop/fo/FOTreeBuilder.java?annotate=1.45#124
Re: validateChildNode prevents extensions.
--- J.Pietschmann [EMAIL PROTECTED] wrote: Finn Bock wrote: An extension mechanism where I can put an unmodified fop.jar and myextension.jar on the CLASSPATH and have it work is a defining issue to me. That's how it should work. The code build into the FOP core should only validate elements from the fo namespace and attributes from no namespace, Provided the extension namespace isn't already hardcoded into FOP (like the fox: one). and call validation for elements and attributes from other namespaces in roder to give them a chance to validate themselves. Errr, elements can't validate themselves, because the validity of an element is defined only by the parent. The recommendation declares, via the content models, which children are valid for each parent, not vice-versa. This logic is naturally (and much more cleanly) stored with the parent in the OO world, allowing Finn's block.java to have different child nodes from FOP's block.java. Furthermore, such a child-level validation would require the kid to be instantiated first. vCN() stops instantiation of the kid from ever occurring if it would be invalid to begin with. Glen
Re: validateChildNode prevents extensions.
Glen Mazza wrote: Provided the extension namespace isn't already hardcoded into FOP (like the fox: one). There shouldn't be extensions hardcoded into the FOP core, at least in the long term. Errr, elements can't validate themselves, because the validity of an element is defined only by the parent. The extension writer decides the content model, and if an extension element is supposed to be child of a fo:block only, the corresponding Java object has to get its parent and verify its actually a fo:block. The recommendation declares, via the content models, which children are valid for each parent, not vice-versa. True for elements from the FO namespace *only*. This logic is naturally (and much more cleanly) stored with the parent in the OO world, allowing Finn's block.java to have different child nodes from FOP's block.java. There is no Finn's block.java in the proper model of doing extensions. An extension writer should only write the extension. The FOP core must 1. Provide a discovery mechanism for the extension. The service file used for this purpose in the maintenance branch can be easily extended just by dropping the extension jar into the classpath. 2. A configuration mechanism for the extension both for default and user supplied values. We don't have this currently. 3. A hook for the extension element factory. Works nicely. 4. A hook for validating the extended content model. 5. Hooks for doing layout and rendering. Especially the API for the last will take some iterations, but this doesn't mean Furthermore, such a child-level validation would require the kid to be instantiated first. vCN() stops instantiation of the kid from ever occurring if it would be invalid to begin with. From the viewpoint of a FO element, any elements (and attributes) from other namespaces are valid and will be instantiated. Then the foreign children get a chance to validate themselves. Granted, visible foreign content should be exclusively used through instream-foreign-object, but this breaks down for extensions like Karen's extension elements shown before or after page breaks. J.Pietschmann
Re: validateChildNode prevents extensions.
--- Finn Bock [EMAIL PROTECTED] wrote: Option #1: 1.) myextension.jar will need a FOElementMapping [1] subclass that will reroute fo:Block from Block.java to FinnBlock.java. Have FinnBlock.java override the vCN() for the new validation rules. This would eventually cause a conflict with the GlenBlock.java from an extension written by you. I don't think so, because there is only one XSL fo:block element, which must have one and only one content model. If I want to incorporate extension elements from multiple extension jars, I'll need to code so accordingly in my own GlenBlock.java, which would incorporate, say, extensions from FinnExtension.java and extensions from SimonExtension.java, and define the ordering and cardinality of the them. Next, I'd have to create a GlenBlockLayoutManager that will take care of all of these different children from different extension elements. The children of an fo:block object are just not dynamically additive: they are precisely ordered with cardinality. For fo:root, for example, the order must be fo:layout-master-set, fo:declarations?, fo:page-sequence+, *in that order*. Content models, derived from DTD models, do not allow for random ordering of child elements. Note this stuff needs to be rendered in layout eventually anyway, so even if you can dynamically discover the children of an FO -- and come up with an algorithm to order them -- you will need to create a LayoutManager would need to be able to dynamically handle them as well--eventually these extensions elements would be conflicting with each other otherwise. Glen
Re: validateChildNode prevents extensions.
On Sun, Aug 29, 2004 at 08:15:38PM +0200, J.Pietschmann wrote: Glen Mazza wrote: You have a new FO, you're going to need to code for them--including ordering and cardinality--in those parents that accept them, This does *not* necessarily mean that *you* should arrange that the extension writer has to replace core FO classes. In fact do either: 1. Declare FOP wont support extensions except in instream-foreign-object, ever, or 2. Provide hooks so that extension writers can get their extensions running with FOP, with or without extensive validation of the extended content model, but at least *without* having to rewrite and replace core FO classes. My thoughts are along the same lines that Jörg has argued. I think we should do option 2. vCN() should be written such that it allows this. Regards, Simon -- Simon Pepping home page: http://www.leverkruid.nl
Re: validateChildNode prevents extensions.
On 29.08.2004 20:57:54 Simon Pepping wrote: On Sun, Aug 29, 2004 at 08:15:38PM +0200, J.Pietschmann wrote: Glen Mazza wrote: You have a new FO, you're going to need to code for them--including ordering and cardinality--in those parents that accept them, This does *not* necessarily mean that *you* should arrange that the extension writer has to replace core FO classes. In fact do either: 1. Declare FOP wont support extensions except in instream-foreign-object, ever, or 2. Provide hooks so that extension writers can get their extensions running with FOP, with or without extensive validation of the extended content model, but at least *without* having to rewrite and replace core FO classes. My thoughts are along the same lines that Jörg has argued. I think we should do option 2. vCN() should be written such that it allows this. While I choose not to participate in FO-tree and layout engine design but having written a number of FOP extensions, I agree with this view, too. Jeremias Maerki
Re: validateChildNode prevents extensions.
--- Finn Bock [EMAIL PROTECTED] wrote: Extension writers has to create a subclass of AbstractLayoutManager (I just use a LeafNodeLayoutManager) and an subclass of Area. But that are normal operations since there are subclasses of those for each element type. I must also add code to the renderer to handle my area, but that is because the renderer code is not flexable enough to handle unknown area classes. I get around that limitation by plugging in a completely new PDF renderer. OK, in other words, you have to change FOP source code to add a new XSL-based extension element. You have no problem philosophically with this. Also, I can't replace the Block class with my subclass in the FOElementMapping without changing FOP sources. OK, you're saying again that you have to change the FOP source code in order to add a new XSL-based extension element, but now you're having a problem with adding *this* code. I'm still not sure why this is causing you so much more consternation--isn't this trivial (even if annoying) to what you will need to do in the other classes? Between changing code in 3 places with no validation for the user community (and tons of NPE/CCE complaints due to badly written FO's for the committers to deal with on the various lists), vs. changing the code in 4 or 5 places *with* validation for the user community (and few if any NPE/CCE complaints), you do have a bit of a tough case to make that the former would win a cost-benefit analysis. Having to subclass the parents will prevent two different unrelated extension from both having fo:block's as parents. Not true--fo:block already allows 20 or so different types of children--all distinct from each other. (But to further simplify your coding, all you have to do is check that the namespace URI is www.finn.com or whatever and you can choose to allow everything from that namespace.) Remember, FOP is basically a compiler--like javac, you have to define its syntax it will accept, and that will require coding. Also, the only difference between an XSL FO and an extension FO is that the latter hasn't been blessed by the W3C yet. Both need validation and coding. But this shouldn't be a problem, because you have to modify the renderers, layout, and/or area objects source code anyway for the extension element to work. It has worked quite well before. Without changing any of FOPs layout or area sources. True. But in the old version, FOP would happily accept, say, an fo:root as a child of an fo:block, or an fo:layout-master-set as a child of an fo:list-item, and subsequently NPE while processing. That model simply had to change. Nobody would respect/use a product that operates that way, or a product based on such a product. It's not like you are losing dynamic run-time loadability here, Oh, yes I am. You will need to better clarify this, because you just said above that you needed to change source code anyway to accomodate your new element. I mean exactly that the validation should be loose. If I need a finnbock:foobar tag as a child of fo:block, fo:block should not prevent me from doing so. Yes it should, if fo:block is to be XSL compliant. The Recommendation defines the content model (i.e., the children) that fo:block is to follow and their ordering. We modify that for the extension elements predefined within FOP--as we're allowed to. But it still has to follow a content model. The sit back, have a beer, and let everything pass through mode of validation I'm not too keen on. ;) I promise that I will not post the resulting bugs to Bugzilla. Good, now we'll just need the promises of 500,000 users as well. ;) You are too smart not to realize that a non-validating XSL parser is going to generate lots of NPE/CCE bugs, subtle and otherwise for the committers and user community to have to deal with. Time spent fixing this junk will not be time spent in the layout and renderers, etc. That will hurt your goals, as well as degrade FOP. Perhaps the extension elements can implement a tag interface to indicate that the extension shouldn't be validated by the parent. Or parhaps the checking could be disabled entirely. Actually, we could do that--fairly simple--let's see what the other committers have to say. We can add a boolean to FOUserAgent called disableValidation, have FOTreeBuilder read it every time it sees an FO in the stream, and on the basis of that decide whether or not to call vCN(). I see two problems though: (1) performance issue--this boolean will need to be read for *every* node in the FO document, (2) FOP will be raising NPE and CCE errors for invalid FO -- it is strange for a program to have a switch that will allow it to blow up with errors, or otherwise allow itself to run in an invalid state. Not many programs provide such an option--that may not generate much customer confidence. But, again, let's see what others have to say.
Re: validateChildNode prevents extensions.
Hello Finn, [BTW, before I get to this topic, as you've probably noticed by now I've finished removing the AddLMVisitor. In the process, I also created about eight new layout manager classes, pulling out the layout business logic that used to be in AddLMVisitor. As a result, the maker system you were suggesting should be MUCH smaller to implement now--probably can be kept in one class similar to [1]. Would you agree? If so, if you still like your suggestion--I don't care either way--feel free to add such a maker system in anytime--Simon also was preferring your design.] --- Finn Bock [EMAIL PROTECTED] wrote: Glen I think that the new validateChildNode() methods are too strict in response to extension elements. Extension elements are handled within validateChildNode() just like regular formatting objects, such as e.g. fox:bookmarks in fo:root [2]. We appear to have two categories of extension elements: 1.) (svg and MathML for example): These are dynamically loadable extension elements that are (1) children of fo-instream-foreign-object and (2) don't affect layout, renderers, the area tree, etc. (i.e., *no* change to FOP source code is needed in order for these elements to work.) FOP, in fo.FOTreeBuilder, already has a couple of hooks for run-time discovery and loading of such extension elements. For these types of extension elements, validateChildNode() doesn't hurt anything. The vCN() in fo-instream-foreign object just enforces, per the spec, that there is only one child, and that it is in a non-XSL namespace. 2.) (fox:bookmarks, fox:outline, etc.) These are non-runtime-loadable extension elements that work directly with formatting objects and whose output must be coded within FOP proper. (fox:bookmarks, for example, include logic in area.AreaTreeHandler, PDFRenderer perhaps, and additional code in the PDF library.) Adding these elements requires not just adding an extension element class but additional code in layout/renderers/area objects, etc. For these extension elements, they have to be validated just like the XSL FO's do: you have to determine which nodes can have these extension elements as children, their location, cardinality, etc., etc. So for these elements, you will probably need to subclass/rewrite the vCNs() of parents which may have them. (Of course, once the element is directly incorporated into FOP, subclassing will no longer be needed.) But this shouldn't be a problem, because you have to modify the renderers, layout, and/or area objects source code anyway for the extension element to work. It's not like you are losing dynamic run-time loadability here, and generally a vCN() does not add much more to the work you have to do. (Actually, vCN() tends to reduce coding complexity of work downstream.) My guess is that the validation should only occur when one fo namespace element is added to another fo element. I don't think you mean that completely--that's too loose. We should be leery of a system that would allow, say, svg:rect to be a child of fo:block. FOP just wouldn't be solid that way, and who would want to maintain the Bugzilla list that would result from that? ;) The benefits of vCN() is to (1) stop problems at the source, prior to creating the node, rather than risk many Bugzilla and FOP-User ML messages of subtle NPE/CCE problems that would otherwise occur downstream, and (2) reduce the amount of sometimes duplicative error checking distracting the business logic downstream, and (3) provide a uniform error-messaging system. For instance, Block.validateChildNode() doesn't allow any of my extension elements as children. Yes, you will need to modify it for your new element. But first you have to (1) define which parents your element is good for, and (2) where they need to be located among those parent's children. The fact that vCN() forces one to stop first and define these things is IMO actually a Good Thing, and would have to be done anyway should the element be eventually incorporated into FOP. (BTW, for extension elements that are valid in multiple places, take a look at our isBlockItem(), isInlineItem() and isNeutralItem() in [3]--you may be able to just place your extension elements there if they are valid in the same places that the elements defined there are.) Sorry for the long post. Glen [1] http://cvs.apache.org/viewcvs.cgi/xml-fop/src/java/org/apache/fop/fo/FOElementMapping.java?rev=1.8view=auto [2] http://cvs.apache.org/viewcvs.cgi/xml-fop/src/java/org/apache/fop/fo/pagination/Root.java?annotate=1.23#100 [3] http://cvs.apache.org/viewcvs.cgi/xml-fop/src/java/org/apache/fop/fo/FObj.java?annotate=1.69#462