Re: Roles (was: antlib)
On Friday 09 May 2003 04:08, Costin Manolache wrote: peter reilly wrote: Using property files is nice but with new attributes to typedef (adaptor for example) it would be better to use an xml file/resource. I think we already agreed on XML - there is no reason to continue adding arguments. This should be independent of using antlibs/jars or XML ns. Hence I think that the root element name should not be antlib as this implies more baggage. (Also my work in progress implementation uses an ant task for the xml parsing and the root element name is the task name ;-)). That's what I would do too ( and why I suggested using ant xml processing for the antlib descriptor ) :-) What baggage are you talking about ? Antlib is what we are trying to do, it would be confusing to use another name for the root element. The baggage is that lib is normally associated with jar files. 1) the code to handle XML namespaces in ProjectHelper2 is not yet complete. - namespaces of attributes is not handled yet - the code uses getQName() on the attributes and does not pass the URI of the attributes to the attribute list given to Easy to fix it to localname, but I don't want to get into ns + attributes, let's leave it for ant1.7 :-) ( or at least wait for the component creation to be done ). The NS standard http://www.w3.org/TR/REC-xml-names/ allows one to do somthing like this: project xmlns:html='http://www.w3.org/TR/REC-html40' target name=t echo html:class=reallyimportantmessage/echo /target /project of course it is up to the ant software to understand the xml file, but unsupported attribute 'class' is not a usefull error message in this case. Yes - but let's first implement namespaces on the elements. We can add code to ignore ( for now ) attributes that are in a different namespace than the element - that would allow various annotations or 3rd party tools. After we see how people use namespaces - we can add more features for the attributes. Attribute + NS affects the introspection. - the uris for project/target elements/attributes are not checked. Project and target are owned by ant, you can't redefine them in antlibs. This is true, but using namespaces one could do: project xmlns:html='http://www.w3.org/TR/REC-html40' html:target name=t echohello world/echo /html:target /project which is clearly wrong - but with the current code gives the misleading error: Could not create task or type of type: target There are plenty of wrong things one can do :-) Is True... We can fix the message to say html:target or use the URI, it's not a show stopper. - the ns standard allows different types of software processing for the different namespaces, if this is to be supported ProjectHelper2 would need to look at the uri before handing the element to the ElementHandler object (see my previous e-mail on the subject) Not sure I agree ( or understand ) this. The idea is to allow a xml ns to be used for purposes other that defining Unknown Elements. My example was an antdoc xml ns. Still don't get it. PH2 creates an object tree - and various element in the tree can access the tree and do whatever they want. PH2 itself shouldn't be involved in this. My idea is to get PH2 to ignore name spaces it does not understand - they then will not form part of the tree. 3) In what ns will the introspected attributes and nested elements of the new elements reside? Some of the previous e-mails assume that they belong in the antlib's namespace - but what about datatypes that extend ant's datatypes - e.g mypath. (This is assuming that the attributes/nested elements are found by introspection - for jmx:... this may not be the case - or a different Class than IntrospectionHelper may be used). Those created by IntrospectionUtil - it doesn't matter, it's set by the It does matter from a build script point of view. addon:copypath path refid=x/ remoteurl url=http://; retry=no/ /addon:copypath is different from: addon:copypath addon:path refid=x/ addon:remoteurl url=http://; retry=no/ /addon:copypath The first case is simple - the current rules cover it. For the second - I don't know how could we handle it with the simple patterns ( createPath / addPath ). What's your proposal ? To apply the simple patterns to the local name ? I propose using the first case. introspection rules. For the new polymorphic tasks - probably the same rules of component creation as in top-level tasks. ( still not sure if we agreed on how many lookup tables we'll use ) 4) the proposed polymorphic element type substitution element type=newtype/ will need to be made ns-aware. either newtype for-element=element/ or the
Re: Roles (was: antlib)
peter reilly wrote: Using property files is nice but with new attributes to typedef (adaptor for example) it would be better to use an xml file/resource. I think we already agreed on XML - there is no reason to continue adding arguments. This should be independent of using antlibs/jars or XML ns. Hence I think that the root element name should not be antlib as this implies more baggage. (Also my work in progress implementation uses an ant task for the xml parsing and the root element name is the task name ;-)). That's what I would do too ( and why I suggested using ant xml processing for the antlib descriptor ) :-) What baggage are you talking about ? Antlib is what we are trying to do, it would be confusing to use another name for the root element. 1) the code to handle XML namespaces in ProjectHelper2 is not yet complete. - namespaces of attributes is not handled yet - the code uses getQName() on the attributes and does not pass the URI of the attributes to the attribute list given to Easy to fix it to localname, but I don't want to get into ns + attributes, let's leave it for ant1.7 :-) ( or at least wait for the component creation to be done ). The NS standard http://www.w3.org/TR/REC-xml-names/ allows one to do somthing like this: project xmlns:html='http://www.w3.org/TR/REC-html40' target name=t echo html:class=reallyimportantmessage/echo /target /project of course it is up to the ant software to understand the xml file, but unsupported attribute 'class' is not a usefull error message in this case. Yes - but let's first implement namespaces on the elements. We can add code to ignore ( for now ) attributes that are in a different namespace than the element - that would allow various annotations or 3rd party tools. After we see how people use namespaces - we can add more features for the attributes. Attribute + NS affects the introspection. - the uris for project/target elements/attributes are not checked. Project and target are owned by ant, you can't redefine them in antlibs. This is true, but using namespaces one could do: project xmlns:html='http://www.w3.org/TR/REC-html40' html:target name=t echohello world/echo /html:target /project which is clearly wrong - but with the current code gives the misleading error: Could not create task or type of type: target There are plenty of wrong things one can do :-) We can fix the message to say html:target or use the URI, it's not a show stopper. - the ns standard allows different types of software processing for the different namespaces, if this is to be supported ProjectHelper2 would need to look at the uri before handing the element to the ElementHandler object (see my previous e-mail on the subject) Not sure I agree ( or understand ) this. The idea is to allow a xml ns to be used for purposes other that defining Unknown Elements. My example was an antdoc xml ns. Still don't get it. PH2 creates an object tree - and various element in the tree can access the tree and do whatever they want. PH2 itself shouldn't be involved in this. 3) In what ns will the introspected attributes and nested elements of the new elements reside? Some of the previous e-mails assume that they belong in the antlib's namespace - but what about datatypes that extend ant's datatypes - e.g mypath. (This is assuming that the attributes/nested elements are found by introspection - for jmx:... this may not be the case - or a different Class than IntrospectionHelper may be used). Those created by IntrospectionUtil - it doesn't matter, it's set by the It does matter from a build script point of view. addon:copypath path refid=x/ remoteurl url=http://; retry=no/ /addon:copypath is different from: addon:copypath addon:path refid=x/ addon:remoteurl url=http://; retry=no/ /addon:copypath The first case is simple - the current rules cover it. For the second - I don't know how could we handle it with the simple patterns ( createPath / addPath ). What's your proposal ? To apply the simple patterns to the local name ? introspection rules. For the new polymorphic tasks - probably the same rules of component creation as in top-level tasks. ( still not sure if we agreed on how many lookup tables we'll use ) 4) the proposed polymorphic element type substitution element type=newtype/ will need to be made ns-aware. either newtype for-element=element/ or the ns prefix - ns uri mapping at the parse time when processing type=newtype will need to be maintained. Probably using the prefix in newtype would be the most intuitive ( element type=antcontrib:if / ), but that will require some tricky change in PH2 to implement. Actually I think change is easy enough. :-) Sorry, I don't understand
RE: Roles (was: antlib)
From: Costin Manolache [mailto:[EMAIL PROTECTED] I think you started with wrong assumptions here. There is no need to change anything in the core or optional tasks, you can have an antlib that uses multiple jars ( and most likely antlibs will eventually use some dependency mechanism and have mutliple jars ). So you want to continue with the aberration of allowing having tasks in the descriptor that cannot be loaded or fail to resolve due to lack of dependencies? This is what we have to allow today in order to have those magic property files that contain all the optional tasks. At least I was striding to get rid of it. But if you impose the rule one antlib one URI (as it was suggested) then you have to continue with this aberration just for backward compatibility. Let me just make clear that I am assuming the content of an antlib is defined by its XML (or whatever) descriptor. I have no problem using XML namespaces as long as they are independent of the antlib and under complete user control (not antlib designer control). In other words the user should be able to decide if s/he wants to load the library on some particular namespace or in the default namespace which is the one used by core. The namespace is not under user control - by definition. Read the W3C spec, it is designed to be fixed, stable, durable, etc. And there is no point in the user changing the namespace URI - the ns is the id or name of the library. There is definetly nothing on W3C about antlib libraries. The URI is just a string and W3C imposes no meaning to it. Whether it is universally unique or not is just suggested not impossed, the same as public-ids for DTDs. As long as you can distinguish between two diferent things that is all that is required. Regarding use of the core namespace if no name conflicts: +1 So I am an antlib writer and have a shitch/ task and because it does not conflict with core I fix it in the core namespace. So ANT 1.7 comes along and decides to add a switch/ task to core. Now what, did 1.7 broke backward compatibility? My antlib is now incompatible with the new version of ANT eventhough no APIs where mofified. Is ant.apache.org gonna monitor all 3rd party antlibs to make sure core never uses a name someone else already used? This is a administration nightmare. This is why I am saying let the user resolve the conflicts, if he decides to use two antlibs with clashes, then allow him to load them is separate namespaces to resolve its own conflicts. So if I say: antlib location=antcontrib.jar/ I will be able to use: if/, switch/, etc. But is I do: project xmlns:cont=mylibs Again - the URI is not under user control, but under the antlib author control. Just like the if and the other task names. Allowing the user to rename tasks would be very wrong and confusing. ( let's rename delete to copy, then import few files - and figure out what the build file is actually doing ). Tell me where in the introspection engine this is required. This is just your idea. Antlib could pick the namespace dynamically at loading time. And lets just say that today I could rename all tasks to french names if I wanted just need to write a properties file. (granted the inner-elements will continue in english, but hey). Jose Alberto
Re: Roles (was: antlib)
On Thu, 8 May 2003 12:30 am, Costin Manolache wrote: The URI however should be chosen by the antlib author ( maybe based on some rules specific to ant ), and should serve as an ID of the library. My proposal is to use the (main) package name. There are other options - but I don't think every end user using it's own name for an antlib is a good one. +1 I believe the URI should be defined by the antlib builder, not the user. It should be opaque - no semantic structure, at least from Ant's processing. An antlib should just declare to what namespace URI it belongs and then that antlib's defs would be accessible through that namespace in the build file. This would allow multiple antlibs to belong to a single namespace, which might be useful for extension purposes. So, something like this antlib uri=blah taskdef typdef /antlib Antlibs could potentially declare themselves to belong to the default namespace. This would handle Ant's existing optional tasks. This facility might be restricted to antlibs found in a particular location. A classloader could probably be associated with the URI, picking up all antlibs declaring the URI. Just some thoughts Conor
RE: Roles (was: antlib)
Jose Alberto Fernandez wrote: As someone already said, it's about not reinventing the wheel, not about enabling the use of fancy tools. But as ubiquitous and accepted as XML namespaces are, I see many things that could be gained from using namespaces. Also, I suspect most users familiar with XML will have had some dose of contact with namespaces. But ANT is not for experience XML users but for Java programmers or C or .NET (with the new tasks). ANT is popular because it is simple to use you do not have construccions that require you to read a full spec to understand. I am not against NS, but I am against forcing people to use them just because. And you instead propose to use something as complex - but different. Your rewriting task names to resolve conflicts is in no way better than use namespace to resolve conflicts. User of ant will be far better learning the standard way to resolve conflicts than learning your syntax and rewriting. We do force people to use XML, and we force them to use a specific DTD ( copy ... ) and semantics. Even Perl forces people to use a certain syntax and rules. If you have a solution to the name conflict that is far better than using the standard solution - then we can consider it. But renaming task names is certainly not. So again you have a two tier world where some things are more core than others. Me as a library provider need to decide now whether to ship my library with a property file so that it can be incorporated seemingly into ANT namespace or use an XML definition and force my users to learn NS. Hu Yes. In the first case you'll need to be very carefull to avoid naming conflicts, and you may not be able to benefit from some tools. In the second - you'll force users to use NS - which is a standard used in almost all XML specifications today. We already forced them to learn XML in the first place, and learning NS won't be a waste of time. project xmlns:cont=urn:uri-supplied-by-ant-user antlib location=antcontrib.jar ns=urn:uri-supplied-by-ant-user/ cont:if/ /project I thing this is what I meant (in escense), with the understanding that: a) the user can use the same URI on several antlibs (any conflicts are his problem) The namespace is _not_ under user control, at least according to W3C. You can't just use whatever URI you want for XSLT or XHTML - the URI of a specification/DTD is defined by that specification. The equivalent of a namespace in a programming language is the package. What you are suggesting is equivalent in letting users pick whatever package they want for a java class, at runtime. BTW, if we are still talking about java programmers using ant - I doubt we'll have that many users who don't understand how package work and have a big shock learning about XML namespaces. Costin
Re: Roles (was: antlib)
Conor MacNeill wrote: On Thu, 8 May 2003 12:30 am, Costin Manolache wrote: The URI however should be chosen by the antlib author ( maybe based on some rules specific to ant ), and should serve as an ID of the library. My proposal is to use the (main) package name. There are other options - but I don't think every end user using it's own name for an antlib is a good one. +1 I believe the URI should be defined by the antlib builder, not the user. It should be opaque - no semantic structure, at least from Ant's processing. An antlib should just declare to what namespace URI it belongs and then that antlib's defs would be accessible through that namespace in the build file. Can you explain why you don't want a semantic structure ? I don't understand why using a java package name - i.e. the base package of the library - as ns is worse than using an arbitrary string. And I don't unserstand why not using the URI in a meaningfull way - to locate the descriptor. If we use an arbitrary string - we'll still have to use a declaration to associate it with a resource. Of course - using the URI as a file is bad, using it as a HTTP is not very good either. But a java package name has all the characteristics that a namespace name needs, and it's intuitive for java developers. This would allow multiple antlibs to belong to a single namespace, which might be useful for extension purposes. So, something like this What would be the benefit ? IMO it would be more confusing. Even if we don't care about tools - having a namespace associated with a clear set of elements and tags is good for clarity. antlib uri=blah taskdef typdef /antlib Antlibs could potentially declare themselves to belong to the default namespace. This would handle Ant's existing optional tasks. This facility might be restricted to antlibs found in a particular location. +1 - the default namespace is a special case. My problem is with spaghetti-namespaces ( that change names or can be combined ). project xmlsns:antcontrib=ant:net.sf.antcontrib antcontrib:if ... would become: project antlib uri=ant:net.sf.antcontrib if In the first case - if's namespace can be used to locate/load the lib. In the second - an explicit load into the default namespace. A classloader could probably be associated with the URI, picking up all antlibs declaring the URI. For advanced uses - ok. For common use - I think using the main class loader and adding the antlibs ( and their dependencies ) to the main loader is far better. By advanced use I mean the case where you want to use multiple versions of an antlib at the same time, or antlibs that have conflicting deps, etc. Costin Just some thoughts Conor
Re: Roles (was: antlib)
Jose Alberto Fernandez wrote: But ANT is not for experience XML users but for Java programmers or C or .NET (with the new tasks). ANT is popular because it is simple to use you do not have construccions that require you to read a full spec to understand. I am not against NS, but I am against forcing people to use them just because. I had never touched xml when I first encountered Ant. But rather than saying: Yuck, I have to learn XML, my reaction was rather, Excellent... I have been meaning to learn about XML anyway. All this talk of namespaces gave me a good reason to go read up on them in case they do become part of ant. But if a custom solution is coded where can I go read up on it... where can I get a second book, or web info on it ifi the manual doesn't seem adequate? If standards are used, then lots of information will be available to make sense of them. I am in favor of using a standards based approach because it will save me work in the long run. Time spent learning namespaces is likely to be time well spent, useful elsewhere. If I have to learn something I'd much rather learn something I might see again. -Gus
Re: Roles (was: antlib)
peter reilly wrote: The NS standard http://www.w3.org/TR/REC-xml-names/ allows one to do somthing like this: project xmlns:html='http://www.w3.org/TR/REC-html40' target name=t echo html:class=reallyimportantmessage/echo /target /project of course it is up to the ant software to understand the xml file, but unsupported attribute 'class' is not a usefull error message in this case. I would make elements from namespaces without associated code in certain positions legal (silently ignored by Ant) or a warning level problem. Same for attributes from namespace which is not the default namespace nor the namespace of the element. This allows buildfile editors to put stuff for other tools into the buildfile in a structured way. This is used for example in XSLT, which allows elements from non-default, non-xslt namespaces as immediate children of xsl:stylesheet, for various purposes, the most oviously useful is extended documentation: xsl:stylesheet version=1.0 xmlns:xsl=http://www.w3.org/1999/Transform; xmlns:doc=http://nwalsh.com/xsldoc; xmlns:xhtml=http://www.w3.org/...; doc:titleA sample stylesheet/doc:title doc:template xhtml:pThe template matching doc:subst what=match/ is used for... /xhtml:p /doc:template xsl:template match=foo ... Attributes could also provide interesting use cases: task crossref:author=J. Random Hacker ... Well, You could achieve the same with PIs and the like, but atributes are much easier to process with XSLT. For example the above could provide an overview of which authors are responsible for which tasks. J.Pietschmann
Re: Roles (was: antlib)
Jose Alberto Fernandez wrote: Is there a DTD for XSLT? Can I validate an XSLT template against a DTD? Not in general. This is a restriction of DTDs, which can't cope with XML namespaces. DTDs are a SGML heritage and predate XML namespaces. You can always construct a DTD which a certain class of (useful) XSL style sheets validates against. You can partially validate arbitrary style sheets against an XSD or a RNG schema. I thought that was not possible given that most of the elements in the template wil be the things I am trying to generate. In the case of XSLT the the URI is really for the XSLT processor, but not XML as such. Well, the p and div element names are for the browser (HTML renderer, to be more precise), not for (X)HTML as such. After all, any XML document is most useful if it is ultimately processed by some software, which necessarily has to have some knowledge on how to handle the information embedded in the pointy brackets. Java packages are global. NS spaces are hyerarchical I can change the meaning of ANT: twenty times inside the same buildfile depending on where I make the xmlns declaration. You confuse the namespace, which is fix and (hopefully) unique which the qname prefix. Don't do this. Read the spec or a good book about this topic. actually I think it is quite complicated in general. The XML namespace syntax is a compromise between providing unique long names to the processor and reasonably short names to human readers. Yes, you can use this to obfuscate XML documents. You don't *have* to obfuscate XML documents though. Many people complained about the potential problems ill written but valid XML documents can pose to unexperienced users as well as for qd hackers (for example, you can't use simple perl regex matching to grab some tuff from the middle of a big XML document, you'll have to parse the whole doc in order resolve prefixes to namespaces). Interestingly, when namespaces were introduced to C++ there weren't much bitchmoan, while it posed exactly the same problems. J.Pietschmann
RE: Roles (was: antlib)
Let's not reinvent the wheel here. The solution for names conflicts is namespaces - not rewriting. If we use a prefix, let's stick with what everyone else is using. Inventing some original solution ( that may or may not be easier or more flexible than the W3C solution ) won't make things better for the user. antlib location=antcontrib.jar prefix=myxyz- / myxyx-if ... is not easier than project xmlns:myxyz=ant:net.sf.antcontrib myxyz:if ... Costin Jose Alberto Fernandez wrote: Hi guys, I was away on vacation so hasn't been around to make comments about the entire discussion. I will try to sumarize here some comments that go across several messages I have read today. The current antlib provides a way for the user of a particular antlib to rename one or more elements that are in conflict with elements of some other antlib it tries to use. As the renaming is local to the project there is no problem; it is up to the user of the antlib to decide what names to use to refer to the loaded things. For example I may use the foreach class of antcontrib but for reasons of my project being in need to also use a foreach defined by some other third party which works diferently. So I could just load it and rename it lets say to forall and use it in my project using that name. It is up to me as the user of the antlib. From the discussion this last few days I like the idea from (I think) Peter/Nicola of having short and long names where the long names are form by adding a prefix defined not by the antlib writer, but by the antlib user: antlib location=antcontrib.jar prefix=myxyz- / which would allowme to use either: if/ or myxyz-if it is upto the user to decide what to use. Of course the same would be for the tasks (i.e., taskdef) that allows loading individual tasks into roles. The same rules of collisions and conflict resolution apply. The important point is for the user (which is the one who has to deal with name clashes) to have control of the final naming scheme used in his/her buildfile. And we are not impossing any wierd semantics or making assumptions, if I decide to use the same prefix for two antlibs it is up to me to make sure there are no conflicts. -Original Message- From: Stefan Bodewig [mailto:[EMAIL PROTECTED] Sent: 02 May 2003 14:35 To: [EMAIL PROTECTED] Subject: Re: Roles (was: antlib) On Wed, 30 Apr 2003, Jose Alberto Fernandez [EMAIL PROTECTED] wrote: The problem you are overlooking is the case of weblogic element in ejbjar, jspc, serverdeploy, etc. Maybe not really overlooking but understimating. The alternative would be to use weblogicjspc and weblogicdeploy for the different interfaces. If they come from different antlibs, we really should use XML namespaces to resolve this. But I now understand that having a table per interface may be convenient (though not strictly necessary). Stefan - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Roles (was: antlib)
On Tue, 06 May 2003, Costin Manolache [EMAIL PROTECTED] wrote: Jose Alberto Fernandez wrote: The important point is for the user (which is the one who has to deal with name clashes) to have control of the final naming scheme used in his/her buildfile. Let's not reinvent the wheel here. The solution for names conflicts is namespaces - not rewriting. +1 to both. Make the use choose the namespace for the antlib he/she wants to use. Stefan
RE: Roles (was: antlib)
Let's not reinvent the wheel here. The solution for names conflicts is namespaces - not rewriting. I agree. With the new ProjectHelper2 everything should be in place to start using namespaces. This would also allow antlibs to have a DTD or XML Schema which could be used in XML editors or for validation. Also namespaces lets the antlib user specify what prefix to use. But it doesn't allow two antlibs to use the same prefix in the context of the same element, which I think is good. If you really want you can use short names with namespaces as well. Just set the default namespace locally. -- knut
RE: Roles (was: antlib)
From: Wannheden, Knut [mailto:[EMAIL PROTECTED] Let's not reinvent the wheel here. The solution for names conflicts is namespaces - not rewriting. I agree. With the new ProjectHelper2 everything should be in place to start using namespaces. I have no problem on allowing people to use namespaces, but I do have a problem on forcing people to use them just because some others want to use some fancy XML tool. The buildfile belongs to the user and s/he should be in charge. This would also allow antlibs to have a DTD or XML Schema which could be used in XML editors or for validation. Well ANT's XML is the result of introspection, and we already know our object model cannot be represented by a simple DTD. I see no way or reson to enforce 3rd party libraries to define their objects to be DTD-able. I am not sure about XMLSchema but my hopes are not too high. Also namespaces lets the antlib user specify what prefix to use. But it doesn't allow two antlibs to use the same prefix in the context of the same element, which I think is good. This sounds proper in theory, but in practice lets see: 1) Lets assume that we still want to be able to chop ANT jars between core and different optional jars which have specific dependencies of diferent packages and such. 2) Now because they are in different antlibs it would mean I am forced to use different namespaces for each. 3) So now you have people using 3rd party tasks like antcontrib without problem and without conflicts, but they would have to change not just one line (to use the antlib) but every bloddy use of the tasks just because they are forced to use name spaces. I doubt many people will be fill happy about that, and the backward compatibility consequences. If you really want you can use short names with namespaces as well. Just set the default namespace locally. I have no problem using XML namespaces as long as they are independent of the antlib and under complete user control (not antlib designer control). In other words the user should be able to decide if s/he wants to load the library on some particular namespace or in the default namespace which is the one used by core. So if I say: antlib location=antcontrib.jar/ I will be able to use: if/, switch/, etc. But is I do: project xmlns:cont=mylibs antlib location=antcontrib.jar usens=cont/ /project then I can use cont:if/, cont:switch/, etc. Which means that the default value for the 'usens' attribute is which assumes some implicit namespace definitions like: xmlns=ant-namespace and probably xmlns:ant=ant-namespace which uses as kosher namespaces as possible, I think. Jose Alberto
RE: Roles (was: antlib)
Let's not reinvent the wheel here. The solution for names conflicts is namespaces - not rewriting. I agree. With the new ProjectHelper2 everything should be in place to start using namespaces. I have no problem on allowing people to use namespaces, but I do have a problem on forcing people to use them just because some others want to use some fancy XML tool. The buildfile belongs to the user and s/he should be in charge. As someone already said, it's about not reinventing the wheel, not about enabling the use of fancy tools. But as ubiquitous and accepted as XML namespaces are, I see many things that could be gained from using namespaces. Also, I suspect most users familiar with XML will have had some dose of contact with namespaces. This would also allow antlibs to have a DTD or XML Schema which could be used in XML editors or for validation. Well ANT's XML is the result of introspection, and we already know our object model cannot be represented by a simple DTD. I see no way or reson to enforce 3rd party libraries to define their objects to be DTD-able. I am not sure about XMLSchema but my hopes are not too high. With roles I think XML Schema could very well be used to validate a buildfile. But I'm not saying that a schema should be enforce. It would be a gain of using XML namespaces. Also namespaces lets the antlib user specify what prefix to use. But it doesn't allow two antlibs to use the same prefix in the context of the same element, which I think is good. This sounds proper in theory, but in practice lets see: 1) Lets assume that we still want to be able to chop ANT jars between core and different optional jars which have specific dependencies of diferent packages and such. 2) Now because they are in different antlibs it would mean I am forced to use different namespaces for each. Is that really so? As I understood it antlibs wouldn't be a requirement for providing Ant tasks and types. I thought the normal taskdef/ and typedef/ would still work as they do now. I suppose it would also be possible to let one antlib extend another one, thus letting it use the same namespace. 3) So now you have people using 3rd party tasks like antcontrib without problem and without conflicts, but they would have to change not just one line (to use the antlib) but every bloddy use of the tasks just because they are forced to use name spaces. To use antcontrib as an antlib they would at the very least have to replace the taskdef/s with an antlib/ element or something, no? But the tasks should still work as they do now using taskdef/. If you really want you can use short names with namespaces as well. Just set the default namespace locally. I have no problem using XML namespaces as long as they are independent of the antlib and under complete user control (not antlib designer control). In other words the user should be able to decide if s/he wants to load the library on some particular namespace or in the default namespace which is the one used by core. So if I say: antlib location=antcontrib.jar/ I will be able to use: if/, switch/, etc. But is I do: project xmlns:cont=mylibs antlib location=antcontrib.jar usens=cont/ /project then I can use cont:if/, cont:switch/, etc. I think the antlib/ shouldn't define the prefix, but the namespace URI instead . Something like: project xmlns:cont=urn:uri-supplied-by-ant-user antlib location=antcontrib.jar ns=urn:uri-supplied-by-ant-user/ cont:if/ /project Of course if the antlib would provide its own namespace in the descriptor. Ant could do some kind of automatic loading when a namespace declaration matching the namespace URI is encountered. But I'm not sure that's a good idea. Which means that the default value for the 'usens' attribute is which assumes some implicit namespace definitions like: xmlns=ant-namespace and probably xmlns:ant=ant-namespace which uses as kosher namespaces as possible, I think. But this would require that the project/ element would define the default namespace like this: project xmlns=ant-namespace ... /project Why not use the empty namespace for Ant core? -- knut
Re: Roles (was: antlib)
Stefan Bodewig wrote: On Tue, 06 May 2003, Costin Manolache [EMAIL PROTECTED] wrote: Jose Alberto Fernandez wrote: The important point is for the user (which is the one who has to deal with name clashes) to have control of the final naming scheme used in his/her buildfile. Let's not reinvent the wheel here. The solution for names conflicts is namespaces - not rewriting. +1 to both. Make the use choose the namespace for the antlib he/she wants to use. If you're reffering to the prefix - of course, that's how NS works. The URI however should be chosen by the antlib author ( maybe based on some rules specific to ant ), and should serve as an ID of the library. My proposal is to use the (main) package name. There are other options - but I don't think every end user using it's own name for an antlib is a good one. Costin
Re: Roles (was: antlib)
format of the definition file. I would propose a root element of antdef and nested elements of typedef and taskdef and a possible description nested element and/or attribute. Or antlib as root element ? I'm pretty sure sooner or later we'll have some conditions or echo or even paths :-) And also dependencies in one form or another. But for start typedef should be enough. I wouldn't use taskdef - just a typedef and the fact that implements Task or has an adapter that implements task 2: either extend the typedef/ task to use the definition file in the same way as property files are deal with at the moment or provide a task - antdef [resource=... | file =...] [classpath attributes and nested elements from typedef/ Again - antlib ... :-) 3: release/document the classloader/ task to manipulate the classpath. Sorry - tomcat took much more than I expected last weekend. 4: Implement the XML ns changes to use the xml definition file possibly using a predefined filename and using a package name. Not sure I understand - which part are you talking about ? Costin Peter On Wednesday 07 May 2003 06:14, Costin Manolache wrote: Let's not reinvent the wheel here. The solution for names conflicts is namespaces - not rewriting. If we use a prefix, let's stick with what everyone else is using. Inventing some original solution ( that may or may not be easier or more flexible than the W3C solution ) won't make things better for the user. antlib location=antcontrib.jar prefix=myxyz- / myxyx-if ... is not easier than project xmlns:myxyz=ant:net.sf.antcontrib myxyz:if ... Costin Jose Alberto Fernandez wrote: Hi guys, I was away on vacation so hasn't been around to make comments about the entire discussion. I will try to sumarize here some comments that go across several messages I have read today. The current antlib provides a way for the user of a particular antlib to rename one or more elements that are in conflict with elements of some other antlib it tries to use. As the renaming is local to the project there is no problem; it is up to the user of the antlib to decide what names to use to refer to the loaded things. For example I may use the foreach class of antcontrib but for reasons of my project being in need to also use a foreach defined by some other third party which works diferently. So I could just load it and rename it lets say to forall and use it in my project using that name. It is up to me as the user of the antlib. From the discussion this last few days I like the idea from (I think) Peter/Nicola of having short and long names where the long names are form by adding a prefix defined not by the antlib writer, but by the antlib user: antlib location=antcontrib.jar prefix=myxyz- / which would allowme to use either: if/ or myxyz-if it is upto the user to decide what to use. Of course the same would be for the tasks (i.e., taskdef) that allows loading individual tasks into roles. The same rules of collisions and conflict resolution apply. The important point is for the user (which is the one who has to deal with name clashes) to have control of the final naming scheme used in his/her buildfile. And we are not impossing any wierd semantics or making assumptions, if I decide to use the same prefix for two antlibs it is up to me to make sure there are no conflicts. -Original Message- From: Stefan Bodewig [mailto:[EMAIL PROTECTED] Sent: 02 May 2003 14:35 To: [EMAIL PROTECTED] Subject: Re: Roles (was: antlib) On Wed, 30 Apr 2003, Jose Alberto Fernandez [EMAIL PROTECTED] wrote: The problem you are overlooking is the case of weblogic element in ejbjar, jspc, serverdeploy, etc. Maybe not really overlooking but understimating. The alternative would be to use weblogicjspc and weblogicdeploy for the different interfaces. If they come from different antlibs, we really should use XML namespaces to resolve this. But I now understand that having a table per interface may be convenient (though not strictly necessary). Stefan - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Roles (was: antlib)
Jose Alberto Fernandez wrote: From: Wannheden, Knut [mailto:[EMAIL PROTECTED] Let's not reinvent the wheel here. The solution for names conflicts is namespaces - not rewriting. I agree. With the new ProjectHelper2 everything should be in place to start using namespaces. I have no problem on allowing people to use namespaces, but I do have a problem on forcing people to use them just because some others want to use some fancy XML tool. The buildfile belongs to the user and s/he should be in charge. Namespaces are the common solution used to resolve name conflicts. I have a big problem on using some original solution like renaming tasks with some prefix. This has nothing to do with fancy XML tools ( in fact, very few editors are able to deal nicely with namespaces ). We have a problem - name conflits - and one solution. I like Perl and the there is more than one way to do things, but in this case we have a standard solution that everyone uses, and it would be very confusing and wrong to force the user to learn a different one. This would also allow antlibs to have a DTD or XML Schema which could be used in XML editors or for validation. Well ANT's XML is the result of introspection, and we already know our object model cannot be represented by a simple DTD. I see no way or reson to enforce 3rd party libraries to define their objects to be DTD-able. I am not sure about XMLSchema but my hopes are not too high. I agree with you on this one. XMLSchema is one of the worse things I've seen. However it is possible to associate a DTD/schema with (most) of the ant ( we even have a dtd generator, that works great with emacs, I use the DTD every day ). And some users may choose to create build files with editors using only the subset of ant that is supported by the editor ( i.e. fits the restrictions of the DTD/schema ). Also namespaces lets the antlib user specify what prefix to use. But it doesn't allow two antlibs to use the same prefix in the context of the same element, which I think is good. This sounds proper in theory, but in practice lets see: 1) Lets assume that we still want to be able to chop ANT jars between core and different optional jars which have specific dependencies of diferent packages and such. 2) Now because they are in different antlibs it would mean I am forced to use different namespaces for each. Why ? I think most people agreed that using the jar file name as a namespace URI is not the best solution. If we go with the package name ( or other solution where the ns is fixed by the antlib creator ) - you can have the files in multiple jars. For package name - the descriptor will have to be in that package. 3) So now you have people using 3rd party tasks like antcontrib without problem and without conflicts, but they would have to change not just one line (to use the antlib) but every bloddy use of the tasks just because they are forced to use name spaces. I think you started with wrong assumptions here. There is no need to change anything in the core or optional tasks, you can have an antlib that uses multiple jars ( and most likely antlibs will eventually use some dependency mechanism and have mutliple jars ). I doubt many people will be fill happy about that, and the backward compatibility consequences. If you really want you can use short names with namespaces as well. Just set the default namespace locally. I have no problem using XML namespaces as long as they are independent of the antlib and under complete user control (not antlib designer control). In other words the user should be able to decide if s/he wants to load the library on some particular namespace or in the default namespace which is the one used by core. The namespace is not under user control - by definition. Read the W3C spec, it is designed to be fixed, stable, durable, etc. And there is no point in the user changing the namespace URI - the ns is the id or name of the library. Regarding use of the core namespace if no name conflicts: +1 So if I say: antlib location=antcontrib.jar/ I will be able to use: if/, switch/, etc. But is I do: project xmlns:cont=mylibs Again - the URI is not under user control, but under the antlib author control. Just like the if and the other task names. Allowing the user to rename tasks would be very wrong and confusing. ( let's rename delete to copy, then import few files - and figure out what the build file is actually doing ). antlib location=antcontrib.jar usens=cont/ /project then I can use cont:if/, cont:switch/, etc. Costin Which means that the default value for the 'usens' attribute is which assumes some implicit namespace definitions like: xmlns=ant-namespace and probably xmlns:ant=ant-namespace which uses as kosher namespaces as possible, I think. Jose Alberto
Re: Roles (was: antlib)
On Wed, 07 May 2003, Costin Manolache [EMAIL PROTECTED] wrote: If you're reffering to the prefix I was. - of course, that's how NS works. I know. Stefan
Re: Roles (was: antlib)
Jose Alberto Fernandez wrote: I have no problem on allowing people to use namespaces, but I do have a problem on forcing people to use them just because some others want to use some fancy XML tool. The buildfile belongs to the user and s/he should be in charge. The buildfile belongs to the user, but the vocabulary belongs to the Ant/Task developers. Do you complain about XHTML/XSLT/SVG/XSLFO/XForm etc. as well? J.Pietschmann
RE: Roles (was: antlib)
From: Costin Manolache [mailto:[EMAIL PROTECTED] Stefan Bodewig wrote: On Tue, 06 May 2003, Costin Manolache [EMAIL PROTECTED] wrote: Jose Alberto Fernandez wrote: The important point is for the user (which is the one who has to deal with name clashes) to have control of the final naming scheme used in his/her buildfile. If you're reffering to the prefix - of course, that's how NS works. The URI however should be chosen by the antlib author ( maybe based on some rules specific to ant ), and should serve as an ID of the library. Why? What has the URI to do with the classes or elements defined in the antlib? You are impossing an arbitrary tie to a uri namespace that has no real meaning whatsoever, since the meaning is on the classes themselves. My proposal is to use the (main) package name. There are other options - but I don't think every end user using it's own name for an antlib is a good one. What I suggest is to let the user of the antlib define whatever URI it wants to whatever antlib it wants and it that way giving him control of which libraries s/he wants to use toguether on the same namespace. The antlib will just load the definitions there and that's it. There is no reason to force people to use different spaces or to enforce rules to administer diferent spaces. Jose Alberto
RE: Roles (was: antlib)
Hi guys, I was away on vacation so hasn't been around to make comments about the entire discussion. I will try to sumarize here some comments that go across several messages I have read today. The current antlib provides a way for the user of a particular antlib to rename one or more elements that are in conflict with elements of some other antlib it tries to use. As the renaming is local to the project there is no problem; it is up to the user of the antlib to decide what names to use to refer to the loaded things. For example I may use the foreach class of antcontrib but for reasons of my project being in need to also use a foreach defined by some other third party which works diferently. So I could just load it and rename it lets say to forall and use it in my project using that name. It is up to me as the user of the antlib.
Re: Roles (was: antlib)
On Fri, 2 May 2003 09:55 pm, peter reilly wrote: No... Ant does not have the infrastructure at the moment to support XML namespaces, and their associated contexts. It may be better to add that infrastructure then :-) It may also be better to use XML Schema's syntax for Polymorphism as the build file could then be validated against a schema. http://www.w3.org/TR/xmlschema-0/#UseDerivInInstDocs Conor
Re: Roles (was: antlib)
peter reilly wrote: Yes, but more infrastructure is needed. (Also, in current ant cvs, ComponentHelper is not used). It's not used because I wanted some feedback on its interfaces. The code is (almost) the same with the one in Project, and it requires one little step to be enabled and pass the ns. My knowledge on this subject is very small, but here is my understanding (based on looking at jelly source code). To support XML ns one needs to know the uri associated with the namespace prefix. If you look in ProjectHelper2, in the inner ElementHandler - the onStartElement() is called with the URI, tag, qname. It creates UnknownElement(). All that's missing is an unknownElement.setNamespace( uri ) ( and adding the getter and setter in UE ). The same prefix may be associated with different uri in the course of processing an xml file. The prefix is usually not relevant. ElementHelper gets it, but I don't think it should use it in any way. By overriding sax.helpers.DefaultHandler#startPrefixMapping and #stopPrefixMapping, one can find out when the prefix mapping space is active and when it is terminated. This is what jelly does. I'm not sure what jelly does, but SAX2 startElement() callback has the info we need ( i.e. the URI ), I don't thik we really need the prefix. It would be more difficult (I may be wrong here) for ant to use this information as resolving of most of tags is done after the xml parsing has completed. When the UE is created we have the URI - and it's trivial to add it. It is not necessary to do this as .DefaultHander#startElement does pass the uri that is associated with the element. This could get stored in the UnknownElement and used for name resolution. (Attributes would also be be considered). Since namespace processing is active, the code should use getLocalName and not getQName. True ( actually there is no getLocalName/getQName - the sax callback has both ). To support antlibs, I am thinking that one could have a mapping table per uri (for element tags), either within the ComponentHelper, or have a ComponentHelper per uri. ComponentHelper's role is to create components - using URI or whatever else it wants. It can maintain one table per URI - or you can have one CH per URI ( I preffer the first option ). One use case I had in mind for CH was a namespace like jmx:..., where the JMXComponentHelper would use the JMX metadata to create the task ( no ant table ). That's clearly outside the scope of antlib or ant ( it's just a custom task ). Costin Peter On Friday 02 May 2003 15:42, Costin Manolache wrote: peter reilly wrote: \ example: typedef myfileset mypath anttest etc .. copy todir=output fileset ant-type=myfileset dir=src newattribute=MyFileSet attribute/ /copy anttest path ant-type=mypath path=build.xml newattribute=MyPath attribute/ /anttest I assume you meant to write ant:type instead of ant-type... No... Ant does not have the infrastructure at the moment to support XML namespaces, and their associated contexts. AFAIK ant _does_ have now the infrastructure to support and use XML namespaces. It is not using it - because we don't know yet what's the best way to do it, but AFAIK the infrastructure exists. ProjectHelper2 uses SAX2, it preserves namespaces in UnknownElement and the code for creation of tasks/types (ComponentHelper) receives the namespace and the name. CH allows plugins - i.e. any task can hook into the component creation and provide it's own mechanism, so you should be able to implement whatever namespace policy you want. Costin - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Roles (was: antlib)
On Wed, 30 Apr 2003, Costin Manolache [EMAIL PROTECTED] wrote: Stefan Bodewig wrote: I don't see a need for separate namespaces depending on the interfaces, so only using the child's element name (and namespace) could be enough. I'm not sure whether I'm overlooking a problem. Not sure I understand. Namespaces are not required to solve the polymorphism problem. Me neither, two overloaded meanings for namespace. Let me try to rephrase: I don't see the need for a different mapping of names to classes depending on the interface, one mapping should be enough. This would mean the child's element name (and XML namespace) should suffice and we don't need the interface the child is expected to implement to determine the class. My concern was the API used by ComponentHelper - I would rather add the parent parameter, even if it's not used now, if we expect we'll find some use cases that will require it ( say in 1.7+ ). OK. An alternative to a magic namespace would be magic attribute names. We can use attributes that contain dashes dependset zipfileset use-as=srcfileset /dependset use-as quite clearly states the user's intent and it is impossible to have an existing attribute for tasks or nested elements. Sounds good ( not use-as, but magic attribute ). Maybe ant:type would be better ? This introduces a magic attribute name and a magic namespace. Works for me. The attribute should be optional Of course. Stefan
Re: Roles (was: antlib)
I have done a little further work on my patch to allow nested elements to have Project type as a constructor. If the object contains both addElement() and createElement(), the addElement() method is used. example: typedef myfileset mypath anttest etc .. copy todir=output fileset ant-type=myfileset dir=src newattribute=MyFileSet attribute/ /copy anttest path ant-type=mypath path=build.xml newattribute=MyPath attribute/ /anttest I will upload the modified patch over the weekend. Peter On Friday 02 May 2003 10:07, Stefan Bodewig wrote: On Wed, 30 Apr 2003, Costin Manolache [EMAIL PROTECTED] wrote: Can you explain again what's wrong with create ? I think I missed it... You can't pass in a subclass of the type returned by the createXYZ method as the object creation happens inside the task. If you want to use a subclass of Path named mypath, you can't use it in tasks that use createPath for the nested path element. My understanding was that whatever is in use today will continue to work the same, we just add a new pattern at the end. Yes, with the caveat that polymorphism doesn't work for the createXYZ case. Stefan - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Roles (was: antlib)
Peter, example: typedef myfileset mypath anttest etc .. copy todir=output fileset ant-type=myfileset dir=src newattribute=MyFileSet attribute/ /copy anttest path ant-type=mypath path=build.xml newattribute=MyPath attribute/ /anttest I assume you meant to write ant:type instead of ant-type... I suppose in both examples all further attributes are for the target class. E.g. both attributes dir and newattribute are for myfileset/. Or would the dir attribute be required for types of copy/'s fileset/ role? -- knut
Re: Roles (was: antlib)
On Wed, 30 Apr 2003, Jose Alberto Fernandez [EMAIL PROTECTED] wrote: The problem you are overlooking is the case of weblogic element in ejbjar, jspc, serverdeploy, etc. Maybe not really overlooking but understimating. The alternative would be to use weblogicjspc and weblogicdeploy for the different interfaces. If they come from different antlibs, we really should use XML namespaces to resolve this. But I now understand that having a table per interface may be convenient (though not strictly necessary). Stefan
Re: Roles (was: antlib)
On Wednesday 30 April 2003 18:17, Costin Manolache wrote: All the discussions so far were about adding an addSomething() - while leaving all existing use cases unmodified. Stefan introduced the concept of a typedef attribute, which allows the ant core code to substitute a different class (named type) without adding code to the current tasks/datatypes. Peter
Re: Roles (was: antlib)
Ok, I have coded ant-type magic attribute over lunch. target name=run depends=init typedef name=myfileset classname=MyFileSet classpath=classes/ mkdir dir=output/ copy todir=output fileset ant-type=myfileset dir=src newattribute=Hi/ /copy /target I will update Patch 19446 over the weekend with the changes. Peter. On Thursday 01 May 2003 09:24, peter reilly wrote: On Wednesday 30 April 2003 18:17, Costin Manolache wrote: All the discussions so far were about adding an addSomething() - while leaving all existing use cases unmodified. Stefan introduced the concept of a typedef attribute, which allows the ant core code to substitute a different class (named type) without adding code to the current tasks/datatypes. Peter - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Roles (was: antlib)
On Tue, 29 Apr 2003, peter reilly [EMAIL PROTECTED] wrote: We are still left the problem of the Type createName() pattern. I don't think that it was solvable. Almost any soltion world require cooperation of the classes implementing the create method. What we can do is adapting all core classes that use the createPattern to also provide the add pattern (with modifications along the lines you suggest) - and make IntrospectionHelper favor addXYZ over createXYZ just as it setXYZ(SomeType) over setXYZ(String) now. Stefan
Re: Roles (was: antlib)
On Tue, 29 Apr 2003, peter reilly [EMAIL PROTECTED] wrote: it is, with an addXYZ(Condition) method marking it up - I'm not really fond of any of the proposed naming conventions so far. Whats wrong with add(Condition) ? Nothing so far. We still need a solution for the ambiguos cases, though. 1.7+ ? Which makes things even more difficult to explain. You can use zipfileset everywhere where fileset is documented, except for task that happen to also have another nested element that is implemented by FileSet such as .. We shouldn't rush 1.6 but get it right now. Stefan
Re: Roles (was: antlib)
On Tue, 29 Apr 2003, Costin Manolache [EMAIL PROTECTED] wrote: Stefan Bodewig wrote: - Should we use (parent, child) tuple to find the class? Should we use (ParentClass, parent, child) tuple ? I'm not sure what the difference is, here. In the second case, the parent class is also used when constructing the child - i.e. introspection or some other info could be used. BTW, by parent I mean parent namespace + parent element name ( even if we don't use ns yet ). OK. I think we'll need ParentClass to apply proper interface resolution. I'm somewhere on the fence, to be honest. I don't see a need for separate namespaces depending on the interfaces, so only using the child's element name (and namespace) could be enough. I'm not sure whether I'm overlooking a problem. In a previous mail I said child alone would already break down today. What I had in mind are things like the fail element nested into sound clashing with the fail task - all those things that make a DTD impossible to write for Ant. But these existing name clashes only exist for the non-overloaded cases that we are still going to support. I.e. they exist because SoundTask defines addFail(SomeObject) which is fine as it is not ambiguos at all. For overloaded methods - one way or another we'll need additional info from the user. I'm fine with either syntax - I would preffer the type attribute ( which could be an ant:type when we add namespaces ), but I'm ok with either solution. An alternative to a magic namespace would be magic attribute names. We can use attributes that contain dashes dependset zipfileset use-as=srcfileset /dependset use-as quite clearly states the user's intent and it is impossible to have an existing attribute for tasks or nested elements. Stefan
Re: Roles (was: antlib)
Stefan Bodewig wrote: On Tue, 29 Apr 2003, Costin Manolache [EMAIL PROTECTED] wrote: Stefan Bodewig wrote: - Should we use (parent, child) tuple to find the class? Should we use (ParentClass, parent, child) tuple ? I'm not sure what the difference is, here. In the second case, the parent class is also used when constructing the child - i.e. introspection or some other info could be used. BTW, by parent I mean parent namespace + parent element name ( even if we don't use ns yet ). OK. I think we'll need ParentClass to apply proper interface resolution. I'm somewhere on the fence, to be honest. Same here :-) I don't see a need for separate namespaces depending on the interfaces, so only using the child's element name (and namespace) could be enough. I'm not sure whether I'm overlooking a problem. Not sure I understand. Namespaces are not required to solve the polymorphism problem. My concern was the API used by ComponentHelper - I would rather add the parent parameter, even if it's not used now, if we expect we'll find some use cases that will require it ( say in 1.7+ ). In a previous mail I said child alone would already break down today. What I had in mind are things like the fail element nested into sound clashing with the fail task - all those things that make a DTD impossible to write for Ant. Adding namespaces could reduce this problem. The fail inside sound could use a different namespace than the core fail element. Without namespaces - the context ( i.e. parent ) seems to be required. In any case - making it available to the helpers that creates the components can't hurt :-) But these existing name clashes only exist for the non-overloaded cases that we are still going to support. I.e. they exist because SoundTask defines addFail(SomeObject) which is fine as it is not ambiguos at all. For overloaded methods - one way or another we'll need additional info from the user. I'm fine with either syntax - I would preffer the type attribute ( which could be an ant:type when we add namespaces ), but I'm ok with either solution. An alternative to a magic namespace would be magic attribute names. We can use attributes that contain dashes dependset zipfileset use-as=srcfileset /dependset use-as quite clearly states the user's intent and it is impossible to have an existing attribute for tasks or nested elements. Sounds good ( not use-as, but magic attribute ). Maybe ant:type would be better ? The attribute should be optional - i.e. required only for overloaded elements, i.e. 2 methods with the same addXXX signature, and it should be matched against the method name. use-as=srcfileset - addSrcfileset() I'm +1 on this solution for the overloading problem, can't think of anything better. Costin
Re: Roles (was: antlib)
On Wednesday 30 April 2003 17:54, Costin Manolache wrote: Stefan Bodewig wrote: On Tue, 29 Apr 2003, peter reilly [EMAIL PROTECTED] wrote: We are still left the problem of the Type createName() pattern. I don't think that it was solvable. Almost any soltion world require cooperation of the classes implementing the create method. What we can do is adapting all core classes that use the createPattern to also provide the add pattern (with modifications along the lines you suggest) - and make IntrospectionHelper favor addXYZ over createXYZ just as it setXYZ(SomeType) over setXYZ(String) now. Can you explain again what's wrong with create ? I think I missed it... The problem is that create returns an object created by the class. Thus the use-as attribute would not be able to substitute a different object. The solution is to get for example Javac to implement a new addClasspath() method, with (minor) mods in the ant framework to allow path objects to be created by the framework. My understanding was that whatever is in use today will continue to work the same, we just add a new pattern at the end. Exactly. Peter
RE: Roles (was: antlib)
From: peter reilly [mailto:[EMAIL PROTECTED] On Wednesday 30 April 2003 16:24, Stefan Bodewig wrote: On Tue, 29 Apr 2003, peter reilly [EMAIL PROTECTED] wrote: it is, with an addXYZ(Condition) method marking it up - I'm not really fond of any of the proposed naming conventions so far. Whats wrong with add(Condition) ? Nothing so far. The only problem I can think of is that it clashes with Collection.add(Object) and thus the problem is that classes may implement it by accident. I my implementation (bugzilla 19446), I use the signature nestedElement(Class), but I would be happy with anything. how about addConfigured(Class), we already use this prefix so it should not be too much clashes to worry about. Jose Alberto
Re: Roles (was: antlib)
First, I must say that it would be nice to have context dependent element names - my core example is the element name containsregexp - is this a condition, filter or selector ? , the different meaning may mean that different classes should implement them. However, I think that expressing this in ant xml dialect is difficult and would result in needless complexity and restrictions. For example if the containsrexexp implemenations are project components which one should be used at the top level? project ... containsregexp id=contains.script .../ Or the example I gave previously: public class MyTask extends Task { public void add(FileSet fileset) { filesets.add(fileset);} public void add(ZipFileSet ignore) { throw new BuildException(Not able to deal with zipped files); } } does one need to do: role name=fileset class=..FileSet/ fileset name=fileset class=...Fileset/ fileset name=zipfileset class =...ZipFileSet/ fileset name=libfileset class=...LibFileSet/ and: public class MyTask extends Task { public void add(FileSet fileset) { if (fileset instanceof ZipFileSet) throw new BuildException(Not able to deal with zipped files); filesets.add(fileset); } } I think that having context dependent script defined names is a bridge to far at this stage in ant's developement. Having unique ant script defined name - class is easy to use, describe, implement and it is what ant does at the moment. Adding context dependent names is not necessary to achieve the goal of user defined conditions, selectors, filters, user classes. (mappers are a little different as the current implemenation uses attributes and not nested elements) Peter Some comments in-line On Monday 28 April 2003 19:55, Jose Alberto Fernandez wrote: Use java rules, (try all interfaces) The parent will tell you what interfaces to use. No need for wild searches. Sorry, when I said try all interfaces, I meant check the parent class for all the interfaces/classes provides by the add() and addConfigured() methods. This is not a wild search ;-) - addComponent( MyRole ) or addMyRole( MyRole ) or both ? I.e. a fixed-name method, with overloading to support multiple roles, or one add method per role ? add(ElementClass) to be consistent with other ant method matching patterns. I prefer just supporting addConfigured, the reason being that makes little sense passing a non configured object of an unknown implementation to the parent. What does it possible can do to it, before it gets configured? It makes as much sense as the current differences between addName() and addConfiguredName(). I do not think that many people make use of the differences (and the addName() pattern is used by default). Using add is usefull for containers to override defaults on contained objects - for example onError = new OnError(ignore) void add(Definer definer) { definer.setOnError(onError); definers.add(definer); } The definer's object default onError may be fail , this would set it to ignore. Peter
RE: Roles (was: antlib)
From: Costin Manolache [mailto:[EMAIL PROTECTED] Jose Alberto Fernandez wrote: Assume class C implements role intrefaces P, Q, and R then typedef name=C1 classname=C/ typedef name=C2 classname=C/ will cause two definitions for P and Q each. There is no way to assign different names separately. On the other approach: role name=p classname=P/ role name=q classname=Q/ p name=C1 classname=C/ q name=C2 classname=C/ here you can get different names for different roles if you so wish. If C implements both P and Q, then it can be used as either P or Q. Whetever name you give it. What's the use case for having p useable only in the P role ( when the class supports both roles ), but not in Q role ? Let's not add restrictions and rules just because we can. No one is restricting you. What I am giving you is the chance to use diferent names if you wish to do so. What is the meaning of: condition property=x and if istrue value=yes/ thenechoyes/echo/then elseechono/echo/else /if istrue value=yes/ /and /condition x should be set, but shall yes be echoed? Although if implements the contract of condition, the meaning of if is to execute its nested tasks also, but for that condition will have to call the execute() by looking at if as a task and not as a condition. So the whole construct falls appart. What do you mean falls appart ? If if implements the contract of condition, it means it should be used as a condition. If it has side-effects - that's part of the implementation, and you should expect them when you use it. If I add a println() in istrue constructor - that will be displayed. If you don't want if to be useable as a condition - don't make it implement condition. It sounds very nice, but the reality is that if already exists and has existed for a long time. Hence we can not go and change it just because it does not fit the pattern you would like. Heck, it is not even our code and there is a BC contract we need to fulfill. The proposal as defined in antlib covers this issues satisfactorily. That is why the proposal is the way it is, we do not have a black sheet of paper, we have an evolving product that imposes constraints on us. Secondly, since classes do not need to implement the interface but may be adapted, you cannot assume much there either. I think I mentioned - this is a special case and it clearly requires a special declaration ( which associates the adapter with the class ). Something like: taskdef name=tomcatEngine class=org.apache.catalina.core.StandardEngine adapter=org.apache.commons.modeler.ant.JMXTaskAdapter / So, how you manage the current data-types which can be used as tasks? Backward compatibility says it needs to be treated internally, but your notation suggests we would have to declare them passing a TaskAdapter otherwise we keep the special cases around in core. Yes, TaskAdapter and taskdef will need to remain special cases for backward compat. And probably tasks will need to be special cases for backward compat. IMO a typedef with a class that implements Task should make that class a task, and be equivalent with a taskdef. The antlib proposal solves this without requiring special cases. It just all naturally falls into place. With the way the proposal does it, we get the cruft out of core and the declarations will continue to be as before because the adaptor association occurs at the role-name level. I think the proposal adds far more cruft and complexity to the core. Backward compat will require special cases anyway. And associating the adapter with the role is completely wrong use of the pattern. What is wrong with been able to define a default value for the adaptor. That is all what the role declaration is doing, indicating what adaptor to use by default if the class does not implement the interface. This is a generic concept and there is no special cases of anything. The case of the if for starts. I would like to get an error if I tried to use an if as a condition because if was not designed to be used that way. And we have to deal with the code we already have. Then don't implement the condition interface. That's how OO programming works - if you implement an interface, java allows that class to be passed as parameter to a method. The class is already out there, we cannot go changing it, we cannot go breaking peoples buildfiles. We need to support what is already there. My argument is more for the common or simple case - which I want to be as simple as possible. For your particular use case - using the interfaces would require the least ammount of work and seems very natural. You declare that a task implements an interface - that means ( usually ) it can be used in that role, just like
Re: Roles (was: antlib)
On Tuesday 29 April 2003 10:46, Jose Alberto Fernandez wrote: If you don't want if to be useable as a condition - don't make it implement condition. It sounds very nice, but the reality is that if already exists and has existed for a long time. Hence we can not go and change it just because it does not fit the pattern you would like. Heck, it is not even our code and there is a BC contract we need to fulfill. if is defined using taskdef/. This places a TaskAdaptor around the class (as the class does not extend TaskDef). So it does not get matched to the add(Condition) method in my local build of ant. The if task had to extend ConditionBase to get the condtions, with the new proposal it could just something like: private ConditionBase conditions; public void add(Condition condition) { conditions.add(condition); } In any case there will always be cases where both proposals will fail ;-) Peter.
Re: Roles (was: antlib)
On Mon, 28 Apr 2003, peter reilly [EMAIL PROTECTED] wrote: 4. public void add(NestedElement anInner) 5. public void addConfigured(NestedElement anInner) Make NestedElement a FileSet and explain how you'd support accepting ClassFileset or ZipFileSet as either srcfiles or destfiles in dependset. Your approach, simple and concise as it is doesn't address the situation where the same interface maps to more than one kind of nested element. Stefan
Re: Roles (was: antlib)
On Mon, 28 Apr 2003, Costin Manolache [EMAIL PROTECTED] wrote: If ParentClass has no addMyChild()/createMyChild() method, we'll need to look up in some table and find a class associated with myChild. OK, well, maybe, see below for an alterbative view. We'll then look in ParentClass for an add method with that particular interface as parameter. The use-case is too simple as the ParentClass could have more than one method with that interface (or even different interfaces implemented by the class mapping to myChild). - should we add a separate table for child-class association - or just use the typedef ? A single table. - Should we use (parent, child) tuple to find the class? Should we use (ParentClass, parent, child) tuple ? I'm not sure what the difference is, here. Or just child name - i.e. context-free ? No, would already break down today. - addComponent( MyRole ) or addMyRole( MyRole ) or both ? I assume you are taking MyRole as the name of the interface here, as I'm not convinced that we need formal roles at all. I.e. a fixed-name method, with overloading to support multiple roles, or one add method per role ? Neither is enough IMHO. - should setComponent be used to indicate single-child ? No. Let's keep set* for Attributes. ( of course, all primitives that can be used as attributes will remain attributes ) Path can already be used as Attribute and as nested element. Let's take DependSet as an example. It has two kinds of nested FileSets, srcfileset and destfileset. For the sake of discussion lets assume that placing ClassFileSet or ZipFileSet for either kind of FileSet was useful - I think it is at least for ZipFileSet. dependset ... zipfileset src=some.zip/ /dependset with the approach you describe, If we follow the name determines implementation route you've described here, both addSrcfileset(FileSet) and addDestfileset(FileSet) would be candidates for methods to call. We need a way to resolve this - probably via an extra attribute that explicitly says I'm a srcfileset. Something like dependset ... zipfileset src=some.zip element=srcfileset/ /dependset The alternative approach (taken by Mutant IIRC) would look like this dependset srcfileset src=some.zip type=zipfileset/ /depenset Here the approach is to look up the expected interface by the method name. I feel this second approach is easier in the (rare?) cases where things are ambiguous, but it also forces people to always explicitly state the type. I'm not sure that the later is a drawback, though. With this approach the parent completely determines which element names are supported as nested elements and at the same time clearly states which interface is expected from the child element. This makes documenting stuff a lot easier. Imagine the nested elements of copy. copy accepts nested filesets or any element whose name maps to a class that extends org.apache.tools.ant.types.FileSet? I think the learning curve for beginners to grok copy ... classfileset .../ zipfileset .../ /copy is steeper than the alternative copy ... fileset type=classfileset .../ fileset type=zipfileset .../ /copy I'm not really sure myself, I've argued the first approach myself when we discussed it the last time around (because the non-ambiguos case requires less typing 8-) Stefan
Re: Roles (was: antlib)
On Tuesday 29 April 2003 12:49, Stefan Bodewig wrote: On Mon, 28 Apr 2003, peter reilly [EMAIL PROTECTED] wrote: 4. public void add(NestedElement anInner) 5. public void addConfigured(NestedElement anInner) Make NestedElement a FileSet and explain how you'd support accepting ClassFileset or ZipFileSet as either srcfiles or destfiles in dependset. Your approach, simple and concise as it is doesn't address the situation where the same interface maps to more than one kind of nested element. Correct. For the dependset problem something allow the lines that you suggested may be possible: dependset srcfileset typedef=zipfileset ../ targetfile .../ /dependset Where typedef is a ant magic attribute for element type. This will need a little bit of fiddling with UnknownElement - there would need to be an addition to getTag() - getTypeDef() which would be the same as getTag() in the normal case. Peter
Re: Roles (was: antlib)
On Tuesday 29 April 2003 13:12, Stefan Bodewig wrote: I think the learning curve for beginners to grok copy ... classfileset .../ zipfileset .../ /copy is steeper than the alternative copy ... fileset type=classfileset .../ fileset type=zipfileset .../ /copy This is debatable as the new type can take completly different attributes and nested elements. Beginners would get equally confused by both options. I'm not really sure myself, I've argued the first approach myself when we discussed it the last time around (because the non-ambiguos case requires less typing 8-) I think we should allow both approaches. Each is valid for some set of use cases. For example condition/ takes a set of conditions, it makes sense for new conditions to be added cleanly : condition outofdate .../ /condition Rather than (to take a perverse example) condition os type=outofdate targetfiles... /condition This could be stopped by having two new introspection rules: 6. public void addOverridableNestedElement(NestedElement anInner) 7. public void addOverridableConfiguredNestedElement(NestedElement anInner) But this does mean changing public methods Peter
Re: Roles (was: antlib)
On Tue, 29 Apr 2003, peter reilly [EMAIL PROTECTED] wrote: This is debatable I said I wasn't sure 8-) I think we should allow both approaches. The main difference between them is that in approach 1 the child determines the name of the element while it is the parent who does so in the second approach. This makes the second approach consistent with existing functionality. allow both doesn't sound like a good idea to me, sounds like a foul compromise because we couldn't get to a decision ;-) Rather than (to take a perverse example) condition os type=outofdate targetfiles... /condition Ouch. I'd rather envision condition condition type=outofdate ... with a new public addCondition(Condition) method. The duplication of Condition is pure incidence, the one in the method name determines the element name, the argument the acceptable types. This could be stopped by having two new introspection rules: One new rule should be enough, and will be enough no matter which route we are going to take. But this does mean changing public methods No way. 8-) Stefan
RE: Roles (was: antlib)
Hi Stefan, Let me start by saying that the roles proposal had not in mind solving the polimorphism issue (which I think is what is at the bottom of your points here). I have no problem on arriving to a solution that covers this aspect, but I do not want it to be the stumbling block on the whole thing. From: Stefan Bodewig [mailto:[EMAIL PROTECTED] On Mon, 28 Apr 2003, Costin Manolache [EMAIL PROTECTED] wrote: - addComponent( MyRole ) or addMyRole( MyRole ) or both ? I assume you are taking MyRole as the name of the interface here, as I'm not convinced that we need formal roles at all. I agree with you here, the main problem I see with adding a MyRole name to the name of the method is that it will hardcode this name in the code of everyone. Moreover this will be a global name which will complicate any handling of 3rd party roles and implementations. I think this would be a name administration nightmare. In the antlib proposal the name of the role (or as I would like to call it the alias for the role is only to help on declarations but with respect to the code of programmers such names are irrelevant, the only thing they care is Java types. Let's take DependSet as an example. It has two kinds of nested FileSets, srcfileset and destfileset. For the sake of discussion lets assume that placing ClassFileSet or ZipFileSet for either kind of FileSet was useful - I think it is at least for ZipFileSet. dependset ... zipfileset src=some.zip/ /dependset with the approach you describe, If we follow the name determines implementation route you've described here, both addSrcfileset(FileSet) and addDestfileset(FileSet) would be candidates for methods to call. We need a way to resolve this - probably via an extra attribute that explicitly says I'm a srcfileset. Something like dependset ... zipfileset src=some.zip element=srcfileset/ /dependset The alternative approach (taken by Mutant IIRC) would look like this dependset srcfileset src=some.zip type=zipfileset/ /depenset Here the approach is to look up the expected interface by the method name. I feel this second approach is easier in the (rare?) cases where things are ambiguous, but it also forces people to always explicitly state the type. I'm not sure that the later is a drawback, though. As I said at the begining roles where not design for doing this. There are several things we need to consider, first is whether the task uses create or add[Configured], certaintly the use of create will disallow we passing a different object. But if you look at ANT today you will see that in both cases we allow passing a different instance via refids (actually is upto the data-type to support this). Now if the datatype where to allow specifying something equivalent to a refid but in place, we could get the desired effect without major changes. So lets assume we add to the FileSet class a new method addConfigured(FileSet inplaceref){ // do something similar to what setRefid() does. } now we can write the above as follows: dependset srcfileset zipfileset src=some.zip/ /srcfileset /depenset which it does not look too bad, and does not need special attributes. With this approach the parent completely determines which element names are supported as nested elements and at the same time clearly states which interface is expected from the child element. This makes documenting stuff a lot easier. Imagine the nested elements of copy. copy accepts nested filesets or any element whose name maps to a class that extends org.apache.tools.ant.types.FileSet? I think the learning curve for beginners to grok copy ... classfileset .../ zipfileset .../ /copy This is what you would get with the current roles as long as copy has something like: addConfigured(Fileset fs){...} is steeper than the alternative copy ... fileset type=classfileset .../ fileset type=zipfileset .../ /copy I'm not really sure myself, I've argued the first approach myself when we discussed it the last time around (because the non-ambiguos case requires less typing 8-) I do not like the type attribute, type is already use on several places like available an I really think the buildfiles from the first one are more easy to understand and write (once you know how to use it). It means that we would need to do a better job describing how things work genericaly and explain better the concept of generic nested elements. But we had always had this problem of explaining how nested things work. Jose Alberto
Re: Roles (was: antlib)
Stefan Bodewig wrote: On Mon, 28 Apr 2003, Costin Manolache [EMAIL PROTECTED] wrote: If ParentClass has no addMyChild()/createMyChild() method, we'll need to look up in some table and find a class associated with myChild. OK, well, maybe, see below for an alterbative view. We'll then look in ParentClass for an add method with that particular interface as parameter. The use-case is too simple as the ParentClass could have more than one method with that interface (or even different interfaces implemented by the class mapping to myChild). You're right. With addConfigured() proposal - it can have only one method with a particular interface, so this is not a case. Let me think about this use case. - should we add a separate table for child-class association - or just use the typedef ? A single table. Good :-) - Should we use (parent, child) tuple to find the class? Should we use (ParentClass, parent, child) tuple ? I'm not sure what the difference is, here. In the second case, the parent class is also used when constructing the child - i.e. introspection or some other info could be used. BTW, by parent I mean parent namespace + parent element name ( even if we don't use ns yet ). Or just child name - i.e. context-free ? No, would already break down today. In this case I think the first change should be in ComponentHelper signature, which now creates the tasks/types/etc based only on NS and element name. - addComponent( MyRole ) or addMyRole( MyRole ) or both ? I assume you are taking MyRole as the name of the interface here, as I'm not convinced that we need formal roles at all. Not even the name of the interface - just allow the user to use an intuitive name. But you're right - this open the case where multiple interfaces with the same parameter are used, and we'll not know what to call. I.e. a fixed-name method, with overloading to support multiple roles, or one add method per role ? Neither is enough IMHO. - should setComponent be used to indicate single-child ? No. Let's keep set* for Attributes. Ok. Let's take DependSet as an example. It has two kinds of nested FileSets, srcfileset and destfileset. For the sake of discussion lets assume that placing ClassFileSet or ZipFileSet for either kind of FileSet was useful - I think it is at least for ZipFileSet. dependset ... zipfileset src=some.zip/ /dependset with the approach you describe, If we follow the name determines implementation route you've described here, both addSrcfileset(FileSet) and addDestfileset(FileSet) would be candidates for methods to call. We need a way to resolve this - probably via an extra attribute that explicitly says I'm a srcfileset. Something like dependset ... zipfileset src=some.zip element=srcfileset/ /dependset Well, the child is still created by the element name - you are solving what method to call problem. The alternative approach (taken by Mutant IIRC) would look like this dependset srcfileset src=some.zip type=zipfileset/ /depenset I feel this second approach is easier in the (rare?) cases where things are ambiguous, but it also forces people to always explicitly state the type. I'm not sure that the later is a drawback, though. Not allways, only for tasks that have overloaded/ambiguous methods. The type could be the local part of the add method ( addZipfileset ), which sounds intuitive. With this approach the parent completely determines which element names are supported as nested elements and at the same time clearly states which interface is expected from the child element. +1 This makes documenting stuff a lot easier. Imagine the nested elements of copy. copy accepts nested filesets or any element whose name maps to a class that extends org.apache.tools.ant.types.FileSet? I think the learning curve for beginners to grok copy ... classfileset .../ zipfileset .../ /copy is steeper than the alternative copy ... fileset type=classfileset .../ fileset type=zipfileset .../ /copy I'm not really sure myself, I've argued the first approach myself when we discussed it the last time around (because the non-ambiguos case requires less typing 8-) For non-overloaded case - which in the original antlib proposal doesn't seem to even be possible - I think determining the method to call is simple, and no extra info is needed. For overloaded methods - one way or another we'll need additional info from the user. I'm fine with either syntax - I would preffer the type attribute ( which could be an ant:type when we add namespaces ), but I'm ok with either solution. Not sure I understand your position on how to create the child class, the overloaded method is related to what add method to call. You seem to preffer use parent element name and child element name. I'm ok with this - we'll just need to figure what syntax will be used to express this, and change
Re: Roles (was: antlib)
On Tue, 29 Apr 2003, Jose Alberto Fernandez [EMAIL PROTECTED] wrote: This continues with the two-tier issue, the core conditions of ANT you can just named, but the third party ones need to use some funny syntax. core conditions would use the same funny syntax, if it wasn't for backwards compatibility, that is. But then again this funny syntax for potentially highly dynamic things like the condition or linereader framework makes me back away from it. I think it also is what made me argue against it about nine months back 8-) OK, so condition outofdate it is, with an addXYZ(Condition) method marking it up - I'm not really fond of any of the proposed naming conventions so far. We still need a solution for the ambiguos cases, though. Stefan
Re: Roles (was: antlib)
On Tuesday 29 April 2003 16:50, Stefan Bodewig wrote: On Tue, 29 Apr 2003, Jose Alberto Fernandez [EMAIL PROTECTED] wrote: This continues with the two-tier issue, the core conditions of ANT you can just named, but the third party ones need to use some funny syntax. core conditions would use the same funny syntax, if it wasn't for backwards compatibility, that is. But then again this funny syntax for potentially highly dynamic things like the condition or linereader framework makes me back away from it. I think it also is what made me argue against it about nine months back 8-) OK, so +1 I will upload an implementation of my proposal to night. (minus the adaptor stuff) condition outofdate it is, with an addXYZ(Condition) method marking it up - I'm not really fond of any of the proposed naming conventions so far. Whats wrong with add(Condition) ? We still need a solution for the ambiguos cases, though. 1.7+ ? Peter
RE: Roles (was: antlib)
From: Costin Manolache [mailto:[EMAIL PROTECTED] Jose Alberto Fernandez wrote: What does it all mean? It means we can now write a task, well typed, which can be accept different XML subelements depending on the declarations of other objects present on the build. The vendor specific elements of ejbjar, jspc and others are typical examples of where this capability can be very useful. Other parts of core could benefit of course. Let me see if I understand corectly what you want. You'll have a task TaskA, with a method addRoleB. And in XML: taskA ... implementationB1 /taskA TaskA doesn't know anything about the implementation - it will only use an interface ( or base class ) RoleB as parameter. I assume you will need some way to associate the tag implementationB1 with a particular class - and this can be very well be done currently with taskdef or typedef ( or with the new role declaration if you want ). The declaration of the class for implementationB1 as a member of the role is what you do equivalent to taskdef or typedef. In any case, all you really need is the tag name and the class name - the roles will be available as interfaces or superclasses. Nothing special for this association. No. If you do it this way it would mean that you cannot expose diferent names for the same class depending on the role. It will also mean that thing that just happen to implement a role (just because of some inheritance) will be made available even though it makes little sense doing so. Ex. if. if is a task. It makes little sense to allow it as a condition, but because it is implemented by subclassing ConditionBase which would implement the role for conditions, it would mean you will declare it in the condition role. (This seems wrong in principle). Secondly, since classes do not need to implement the interface but may be adapted, you cannot assume much there either. The second part is making IntrospectionHelper recognize a child that doesn't fit the current patterns ( i.e. no addImplementationB1 ), and instead of reporting an error look up the child by the name and create the type, then check the interfaces implemented by the class and see if any method in the parent matches. Is there anything else ? You can only check for those interfaces where the class was registered to use that element name (you cannot blindly look at all possible interfaces). 2) What do they do that is no possible in ANT: They allow IntrospectionHelper to connect an XML subelement eventhough introspection cannot find a create or add/Configured method for it. It is a well typed methanism, the parent object will only be passed objects that it knows how to deal with. And the parent object does not need to have any knowledge of what currently available members are on the role. Yes, parent needs one addXXX method with a typed parameter, and the child needs to be matched against it. What I don't understand is why should we just use the existing typedef and just add this new pattern to IntrospectionHelper. Because the proposal declares on a Role by role basis. There is no assumption the same name will be used for all roles, nor that you want to always register all possible roles. Also notice that Roles do not supercede DynamicConfigurator. On one hand roles let external implementations to be considered as possible subelements of a parent object, on the other hand, DynamicConfigurator allows a node to decide given its current state what is the meaning of a particular element. This cannot be done by roles in the general case, and that is good. Usage of Roles: == The principle is very simple: a) A role is defined by an interface. This interface is the parameter for a new special family of addConfigured(interface) methods. +1 on role defined by an interface ( or base class - I don't see any reason to restrict it to only interfaces ). Looks neater :-). But I have no big hangups as long as we can clearly distinguish between named element add/create methods and the ones for roles. I'm not sure a special name is actually required ( addConfigured) - just an add or set method with the interface/class as parameter, and then match them on type. the idea of using addConfigured as the name in because I think we need to be clear on the parsing rules for this objects. Allowing passing not configured objects seem to make little sense since the implementation is completely blackboxed to the parent node. Also, set methods are for attributes only (has that changed?) so they do not apply here. b) When IntrospectionHelper fails to find a create/add method for the element, it will look at all the roles used in the addConfigured methods and on each of those roles will try to find an object declared with that element-tag name. If one and only one
RE: Roles (was: antlib)
Jose Alberto Fernandez wrote: You'll have a task TaskA, with a method addRoleB. And in XML: taskA ... implementationB1 /taskA TaskA doesn't know anything about the implementation - it will only use an interface ( or base class ) RoleB as parameter. I assume you will need some way to associate the tag implementationB1 with a particular class - and this can be very well be done currently with taskdef or typedef ( or with the new role declaration if you want ). The declaration of the class for implementationB1 as a member of the role is what you do equivalent to taskdef or typedef. Why is this required ? typedef should be enough for most common cases - the role declaration is already included in the .class ( i.e. interfaces implemented by the class ) In any case, all you really need is the tag name and the class name - the roles will be available as interfaces or superclasses. Nothing special for this association. No. If you do it this way it would mean that you cannot expose diferent names for the same class depending on the role. It will also mean that That's not true. You can declare a class with as many names you want. You can have multiple typedef and taskdef, each with a different name, but same class. thing that just happen to implement a role (just because of some inheritance) will be made available even though it makes little sense doing so. Ex. if. if is a task. It makes little sense to allow it as a condition, but because it is implemented by subclassing ConditionBase which would implement the role for conditions, it would mean you will declare it in the condition role. (This seems wrong in principle). Not sure I understand the if example. My feeling is that if should be useable in a condition role. In general - if you extend a class or implement an interface you assume a specific contract. Implementing an interface ( directly or by inheritance) and not supporting that particular role is wrong from an OO programming point of view. Secondly, since classes do not need to implement the interface but may be adapted, you cannot assume much there either. I think I mentioned - this is a special case and it clearly requires a special declaration ( which associates the adapter with the class ). Something like: taskdef name=tomcatEngine class=org.apache.catalina.core.StandardEngine adapter=org.apache.commons.modeler.ant.JMXTaskAdapter / The second part is making IntrospectionHelper recognize a child that doesn't fit the current patterns ( i.e. no addImplementationB1 ), and instead of reporting an error look up the child by the name and create the type, then check the interfaces implemented by the class and see if any method in the parent matches. Is there anything else ? You can only check for those interfaces where the class was registered to use that element name (you cannot blindly look at all possible interfaces). Why do you think it is blindly ? You have a parent that has a: setFoo( Interface1 ) and a child that implements Interface1. We could have both the redundant role and the interface - if you want explicit control ( for example prevent a class for working in a role, even if it implements that interface ). I don't see the use case, but if you really need it. My argument is more for the common or simple case - which I want to be as simple as possible. For your particular use case - using the interfaces would require the least ammount of work and seems very natural. You declare that a task implements an interface - that means ( usually ) it can be used in that role, just like any other class that implements that interface. If you implement Runnable - it is supposed that you can be used as a parameter to Thread. I feel it's a programming error to implement an interface but not support its contract, and it's wrong to require an additional declaration (I really implement the interface). 2) What do they do that is no possible in ANT: They allow IntrospectionHelper to connect an XML subelement eventhough introspection cannot find a create or add/Configured method for it. It is a well typed methanism, the parent object will only be passed objects that it knows how to deal with. And the parent object does not need to have any knowledge of what currently available members are on the role. Yes, parent needs one addXXX method with a typed parameter, and the child needs to be matched against it. What I don't understand is why should we just use the existing typedef and just add this new pattern to IntrospectionHelper. Because the proposal declares on a Role by role basis. There is no assumption the same name will be used for all roles, nor that you want to always register all possible roles. ??? My point is that implements can be used to solve the proble you describe. You can also solve it as in the proposal ( by using the
Re: Roles (was: antlib)
On Monday 28 April 2003 17:28, peter reilly wrote: An object of Cimpl gets method 3, An object of ABImpl is ambiguous and is allowed. That should be not allowed Peter
RE: Roles (was: antlib)
From: Costin Manolache [mailto:[EMAIL PROTECTED] Jose Alberto Fernandez wrote: In any case, all you really need is the tag name and the class name - the roles will be available as interfaces or superclasses. Nothing special for this association. No. If you do it this way it would mean that you cannot expose diferent names for the same class depending on the role. It will also mean that That's not true. You can declare a class with as many names you want. You can have multiple typedef and taskdef, each with a different name, but same class. The point is that with your approach typedef will tie the name to that class on ALL interfaces implemented by the class. On the other hand, in my approach the mane is tie to the class on a role by role basis. Assume class C implements role intrefaces P, Q, and R then typedef name=C1 classname=C/ typedef name=C2 classname=C/ will cause two definitions for P and Q each. There is no way to assign different names separately. On the other approach: role name=p classname=P/ role name=q classname=Q/ p name=C1 classname=C/ q name=C2 classname=C/ here you can get different names for different roles if you so wish. thing that just happen to implement a role (just because of some inheritance) will be made available even though it makes little sense doing so. Ex. if. if is a task. It makes little sense to allow it as a condition, but because it is implemented by subclassing ConditionBase which would implement the role for conditions, it would mean you will declare it in the condition role. (This seems wrong in principle). Not sure I understand the if example. My feeling is that if should be useable in a condition role. In general - if you extend a class or implement an interface you assume a specific contract. Implementing an interface ( directly or by inheritance) and not supporting that particular role is wrong from an OO programming point of view. What is the meaning of: condition property=x and if istrue value=yes/ thenechoyes/echo/then elseechono/echo/else /if istrue value=yes/ /and /condition x should be set, but shall yes be echoed? Although if implements the contract of condition, the meaning of if is to execute its nested tasks also, but for that condition will have to call the execute() by looking at if as a task and not as a condition. So the whole construct falls appart. Secondly, since classes do not need to implement the interface but may be adapted, you cannot assume much there either. I think I mentioned - this is a special case and it clearly requires a special declaration ( which associates the adapter with the class ). Something like: taskdef name=tomcatEngine class=org.apache.catalina.core.StandardEngine adapter=org.apache.commons.modeler.ant.JMXTaskAdapter / So, how you manage the current data-types which can be used as tasks? Backward compatibility says it needs to be treated internally, but your notation suggests we would have to declare them passing a TaskAdapter otherwise we keep the special cases around in core. With the way the proposal does it, we get the cruft out of core and the declarations will continue to be as before because the adaptor association occurs at the role-name level. The second part is making IntrospectionHelper recognize a child that doesn't fit the current patterns ( i.e. no addImplementationB1 ), and instead of reporting an error look up the child by the name and create the type, then check the interfaces implemented by the class and see if any method in the parent matches. Is there anything else ? You can only check for those interfaces where the class was registered to use that element name (you cannot blindly look at all possible interfaces). Why do you think it is blindly ? You have a parent that has a: setFoo( Interface1 ) and a child that implements Interface1. The case of the if for starts. I would like to get an error if I tried to use an if as a condition because if was not designed to be used that way. And we have to deal with the code we already have. We could have both the redundant role and the interface - if you want explicit control ( for example prevent a class for working in a role, even if it implements that interface ). I don't see the use case, but if you really need it. I think we need it. But I wouldn't mind to provide syntactic sugar to allow saying add this class to every possible role it implements (as far as the system knows). My argument is more for the common or simple case - which I want to be as simple as possible. For your particular use case - using the interfaces would require the least ammount of work and seems
Re: Roles (was: antlib)
My comments in-line: On Monday 28 April 2003 16:35, Costin Manolache wrote: To keep things simple and make it easier to get an agreement - let's let adapters out, and focus on the core issue. IMO it seems what everything leads to is the need to extend the introspection patterns with another case. Let's agree on this pattern first. Assuming: parent myChild /parent If ParentClass has no addMyChild()/createMyChild() method, we'll need to look up in some table and find a class associated with myChild. ( it can be the roles table, or just the typedef table, or some other table that uses the context info or adapters ). Then we'll find some interfaces associated with MyChildClass - either all interfaces, all interfaces and base classes, or only an explicit set declared in some other data strucutures. Each of the interface will be a potential role. We'll then look in ParentClass for an add method with that particular interface as parameter. The points of disagreement: - should we add a separate table for child-class association - or just use the typedef ? We should use the contents of typedef - Should we use (parent, child) tuple to find the class? Should we use (ParentClass, parent, child) tuple ? Or just child name - i.e. context-free ? The name should be context-free. - try all interfaces - or have some data structures to restrict to only a subset ? Use java rules, (try all interfaces) - addComponent( MyRole ) or addMyRole( MyRole ) or both ? I.e. a fixed-name method, with overloading to support multiple roles, or one add method per role ? add(ElementClass) to be consistent with other ant method matching patterns. In the second case, we'll need some additional metadata to associate the role interface with the suffix of the add method. ( MyRole - org.apache.tools.ant.MyRoleInterface ) - should setComponent be used to indicate single-child ? ( of course, all primitives that can be used as attributes will remain attributes ) No, setComponent() should just of an attribute 'component=value' as per current ant method pattern matching/ Peter
Re: Roles (was: antlib)
On Monday 28 April 2003 18:40, Jose Alberto Fernandez wrote: condition property=x and if istrue value=yes/ thenechoyes/echo/then elseechono/echo/else /if istrue value=yes/ /and /condition This particular example does not get through the rules, If extends ConditionBase, but does not extend Task, it is declared by a taskdef/ and thus gets the implicate TaskAdapter wrapper. Thus the object presented to the add(Condition condition) method does not extend Condition. In general however, this is a problem. One example in the current code is uptodate, this can be used in condition/ and as a task. When used as a task, it can set a property, when used as a condition, the property attribute is ignored. Cheers, Peter
RE: Roles (was: antlib)
From: Costin Manolache [mailto:[EMAIL PROTECTED] To keep things simple and make it easier to get an agreement - let's let adapters out, and focus on the core issue. IMO it seems what everything leads to is the need to extend the introspection patterns with another case. Let's agree on this pattern first. Assuming: parent myChild /parent If ParentClass has no addMyChild()/createMyChild() method, we'll need to look up in some table and find a class associated with myChild. ( it can be the roles table, or just the typedef table, or some other table that uses the context info or adapters ). Then we'll find some interfaces associated with MyChildClass - either all interfaces, all interfaces and base classes, or only an explicit set declared in some other data strucutures. Each of the interface will be a potential role. We'll then look in ParentClass for an add method with that particular interface as parameter. I think my main point of disagreement is the assumption that you can assume a unique definition for myChild. As with the jboss example of my previous message there may be several definitions depending of the context of usage. What this means is that you first need to look at the parent to get the context of usages and then look for myChild given that context. Once you do that the rest is trivial. This means that there should be one table per role-interface. This is all introspection has to do. How we fill this tables we can treat separately, I agree. The points of disagreement: - should we add a separate table for child-class association - or just use the typedef ? - Should we use (parent, child) tuple to find the class? Should we use (ParentClass, parent, child) tuple ? Or just child name - i.e. context-free ? As I said, it should be (ParentClass, childname) -- (RoleInterface, implementationInstance). If there is no unique answer we have an ambiguity. After this use method implementing RoleInterface and pass implementationInstance. - try all interfaces - or have some data structures to restrict to only a subset ? - addComponent( MyRole ) or addMyRole( MyRole ) or both ? I.e. a fixed-name method, with overloading to support multiple roles, or one add method per role ? In the second case, we'll need some additional metadata to associate the role interface with the suffix of the add method. ( MyRole - org.apache.tools.ant.MyRoleInterface ) I prefer a fix method, there is no need to add a name that would have to be global forever because it will be ingrane on every class implementation. - should setComponent be used to indicate single-child ? ( of course, all primitives that can be used as attributes will remain attributes ) I do not like giving special priviledges to one and not the other. If and when we change so that setFoo can be used to signal just one Foo element, then we can do the same for roles. Otherwise it is just as simple to ask users to do their own checking like they do for addFoo today. The syntax used to create the data structures, adapters, antlib, etc can be resolved separately - let's just add the extra introspection pattern. Fine. J.A. Costin - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Roles (was: antlib)
From: peter reilly [mailto:[EMAIL PROTECTED] My comments in-line: On Monday 28 April 2003 16:35, Costin Manolache wrote: To keep things simple and make it easier to get an agreement - let's let adapters out, and focus on the core issue. IMO it seems what everything leads to is the need to extend the introspection patterns with another case. Let's agree on this pattern first. Assuming: parent myChild /parent If ParentClass has no addMyChild()/createMyChild() method, we'll need to look up in some table and find a class associated with myChild. ( it can be the roles table, or just the typedef table, or some other table that uses the context info or adapters ). Then we'll find some interfaces associated with MyChildClass - either all interfaces, all interfaces and base classes, or only an explicit set declared in some other data strucutures. Each of the interface will be a potential role. We'll then look in ParentClass for an add method with that particular interface as parameter. The points of disagreement: - should we add a separate table for child-class association - or just use the typedef ? We should use the contents of typedef This will not do for vendor cases and such. See my comments to Contin. - Should we use (parent, child) tuple to find the class? Should we use (ParentClass, parent, child) tuple ? Or just child name - i.e. context-free ? The name should be context-free. -1 you need the context of usage. - try all interfaces - or have some data structures to restrict to only a subset ? Use java rules, (try all interfaces) The parent will tell you what interfaces to use. No need for wild searches. - addComponent( MyRole ) or addMyRole( MyRole ) or both ? I.e. a fixed-name method, with overloading to support multiple roles, or one add method per role ? add(ElementClass) to be consistent with other ant method matching patterns. I prefer just supporting addConfigured, the reason being that makes little sense passing a non configured object of an unknown implementation to the parent. What does it possible can do to it, before it gets configured? In the second case, we'll need some additional metadata to associate the role interface with the suffix of the add method. ( MyRole - org.apache.tools.ant.MyRoleInterface ) - should setComponent be used to indicate single-child ? ( of course, all primitives that can be used as attributes will remain attributes ) No, setComponent() should just of an attribute 'component=value' as per current ant method pattern matching/ Agreed. Jose Alberto Peter - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Roles (was: antlib)
Jose Alberto Fernandez wrote: Assume class C implements role intrefaces P, Q, and R then typedef name=C1 classname=C/ typedef name=C2 classname=C/ will cause two definitions for P and Q each. There is no way to assign different names separately. On the other approach: role name=p classname=P/ role name=q classname=Q/ p name=C1 classname=C/ q name=C2 classname=C/ here you can get different names for different roles if you so wish. If C implements both P and Q, then it can be used as either P or Q. Whetever name you give it. What's the use case for having p useable only in the P role ( when the class supports both roles ), but not in Q role ? Let's not add restrictions and rules just because we can. What is the meaning of: condition property=x and if istrue value=yes/ thenechoyes/echo/then elseechono/echo/else /if istrue value=yes/ /and /condition x should be set, but shall yes be echoed? Although if implements the contract of condition, the meaning of if is to execute its nested tasks also, but for that condition will have to call the execute() by looking at if as a task and not as a condition. So the whole construct falls appart. What do you mean falls appart ? If if implements the contract of condition, it means it should be used as a condition. If it has side-effects - that's part of the implementation, and you should expect them when you use it. If I add a println() in istrue constructor - that will be displayed. If you don't want if to be useable as a condition - don't make it implement condition. Secondly, since classes do not need to implement the interface but may be adapted, you cannot assume much there either. I think I mentioned - this is a special case and it clearly requires a special declaration ( which associates the adapter with the class ). Something like: taskdef name=tomcatEngine class=org.apache.catalina.core.StandardEngine adapter=org.apache.commons.modeler.ant.JMXTaskAdapter / So, how you manage the current data-types which can be used as tasks? Backward compatibility says it needs to be treated internally, but your notation suggests we would have to declare them passing a TaskAdapter otherwise we keep the special cases around in core. Yes, TaskAdapter and taskdef will need to remain special cases for backward compat. And probably tasks will need to be special cases for backward compat. IMO a typedef with a class that implements Task should make that class a task, and be equivalent with a taskdef. With the way the proposal does it, we get the cruft out of core and the declarations will continue to be as before because the adaptor association occurs at the role-name level. I think the proposal adds far more cruft and complexity to the core. Backward compat will require special cases anyway. And associating the adapter with the role is completely wrong use of the pattern. The case of the if for starts. I would like to get an error if I tried to use an if as a condition because if was not designed to be used that way. And we have to deal with the code we already have. Then don't implement the condition interface. That's how OO programming works - if you implement an interface, java allows that class to be passed as parameter to a method. My argument is more for the common or simple case - which I want to be as simple as possible. For your particular use case - using the interfaces would require the least ammount of work and seems very natural. You declare that a task implements an interface - that means ( usually ) it can be used in that role, just like any other class that implements that interface. If you implement Runnable - it is supposed that you can be used as a parameter to Thread. I feel it's a programming error to implement an interface but not support its contract, and it's wrong to require an additional declaration (I really implement the interface). Remember part of the problem is that we need to deal with the code that is already out there which is not neat at all on these respects. However we shouldn't add complexity and make things harder just because some old code is bad. If we think that if shouldn't implement condition - and preventing it to be used as a condition is very important - then we should fix if. BTW, another solution is to enhance the pattern and have a setParent() method in the child. Then if impl. can check the parent and if it's not a task container then throw an exception. If you have an addFoo() and a foo child - I assume the old pattern will be used, not the roles ( backward compat, etc ). The roles would apply if you have a foo child and no addFoo() - you first create foo using the typedef/taskdef/componentDef, then look at the interfaces and find the addInterface() method. You cannot do it this way. Because foo may mean different classes depending on the roles of interest.
Re: Roles (was: antlib)
Jose Alberto Fernandez wrote: What does it all mean? It means we can now write a task, well typed, which can be accept different XML subelements depending on the declarations of other objects present on the build. The vendor specific elements of ejbjar, jspc and others are typical examples of where this capability can be very useful. Other parts of core could benefit of course. Let me see if I understand corectly what you want. You'll have a task TaskA, with a method addRoleB. And in XML: taskA ... implementationB1 /taskA TaskA doesn't know anything about the implementation - it will only use an interface ( or base class ) RoleB as parameter. I assume you will need some way to associate the tag implementationB1 with a particular class - and this can be very well be done currently with taskdef or typedef ( or with the new role declaration if you want ). In any case, all you really need is the tag name and the class name - the roles will be available as interfaces or superclasses. Nothing special for this association. The second part is making IntrospectionHelper recognize a child that doesn't fit the current patterns ( i.e. no addImplementationB1 ), and instead of reporting an error look up the child by the name and create the type, then check the interfaces implemented by the class and see if any method in the parent matches. Is there anything else ? 2) What do they do that is no possible in ANT: They allow IntrospectionHelper to connect an XML subelement eventhough introspection cannot find a create or add/Configured method for it. It is a well typed methanism, the parent object will only be passed objects that it knows how to deal with. And the parent object does not need to have any knowledge of what currently available members are on the role. Yes, parent needs one addXXX method with a typed parameter, and the child needs to be matched against it. What I don't understand is why should we just use the existing typedef and just add this new pattern to IntrospectionHelper. Also notice that Roles do not supercede DynamicConfigurator. On one hand roles let external implementations to be considered as possible subelements of a parent object, on the other hand, DynamicConfigurator allows a node to decide given its current state what is the meaning of a particular element. This cannot be done by roles in the general case, and that is good. Usage of Roles: == The principle is very simple: a) A role is defined by an interface. This interface is the parameter for a new special family of addConfigured(interface) methods. +1 on role defined by an interface ( or base class - I don't see any reason to restrict it to only interfaces ). I'm not sure a special name is actually required ( addConfigured) - just an add or set method with the interface/class as parameter, and then match them on type. b) When IntrospectionHelper fails to find a create/add method for the element, it will look at all the roles used in the addConfigured methods and on each of those roles will try to find an object declared with that element-tag name. If one and only one match is found then the instantiation is successful and the new object will be configured; otherwise it is an error and parsing stops. I disagree here. If the role is associated with an interface, then the declaration is part of each task/type class. If you implement/extend that interface/class - then you have this role. Any extra declaration is redundant - unless you want to declare a wrapper ( see below ). c) The configured object may or may not implement the Role interface, if it does not, an Adaptor object may be instantiated as a proxy for the object. Which adaptor is used depends on how the implementation was declared. +1 here - I think the taskdef/typedef declarations ( which I would like merged in a single component declaration ) should take an extra adapter= attribute, to allow this wrapping. d) The resulting object is passed as an argument to the addConfigured() method. +1 ( with the comments above ). Declaration of roles: A role definition associates a name with an (Interface,Adaptor) pair. The only reason for associating a name with the role is to ease notation when declaring members of a role. Why ? All the user needs to do is associate a name with an implementation class. You need the impl. class anyway - and so the name, but the roles will be available as soon as you have the impl. class. You only need an additional attribute if you want to wrap. Notice that the same interface or the same Adaptor may appear in multiple declarations. This only means that depending on the name used the adaptor of choice will be different. There can only be one pair associated with each name. I don't see any reason for that. A class can implement multiple interfaces, so it can have multiple roles. No need to add arbitrary restrictions.