Hi Peter,

Thanks for the long reply! I have a few questions and a suggestion (inline).

Peter Reilly wrote:

Sorry Gus,
I meant to respond earlier but I am moving to a new computer
and some things got lost.

The main reason the example is confusing is that macrodef, despite
it's name, does not do real textual  substition, it sees a Dom like tree
of elements (a tree of UnknownElements with paired RuntimeConfigurables)
and not the raw texual angley brackets.

A simple example should make this clear. Assume first that namespaced
xml does not support prefix free elements and there is a class A

class A {
  public void addFileSet(FileSet s) {}
}

and class B:
class B {
  public void addFileSet(FileSet s) {}
}

Now suppose that A is a type a in namespace antlib:net.a
and B is a type b in namespace antlib:net.b.
The following would be correct xml:
<ant:project xmlns:a="antlib:net.a" xmlns:b="antlib:net.b"
            xmnls:ant="antlib:org.apache.tools.ant">
 <a:a>
    <a:fileset dir="."/>
 </a:a>

 <b:b>
    <b:fileset dir="."/>
  </b:b>

</ant:project>

This makes sense, and only requires that the program (ant) has either separate fileset implementations ot associate with <a:fileset> and <b:fileset> or has some way of knowing that both are equivalent to <ant:fileset>. All the name spaces are specified explicitly and so there is no confusion here.



Now it is understandable that the following does not work:

 <ant:macrodef name="c">
    <ant:element name="files">
    <ant:sequential>
        <a:a>
          <ant:files/>
         </a:a>
         <b:b>
           <ant:files/>
         </b:b>
    </ant:sequential>
 </ant:macrodef>

as there is no set of xml dom elements that will be
acceptable to a:a and b:a.

XmlNs does have the concept of a default ns prefix and a not specified ns prefix.

First the default ns prefix.
This is what Dominique tried to use.

 <ant:macrodef name="c">
    <ant:element name="files">
    <ant:sequential>
        <a xmlns="antlib:net.a">
          <ant:files/>
         </a>
         <b xmlns="antlib:net.b">
           <ant:files/>
         </b>
    </ant:sequential>
 </ant:macrodef>

 <ant:c>
   <files xmlns="antlib:org.apache.tools.ant">
      <fileset dir="."/>
    </files>
  </ant:c>

This will fail as the fileset element is in the "antlib:org.apache.tools.ant"
namespace and not in the "antlib:net.a" or "antlib:net.b" namespaces.


The not-specified ns prefix (I think) is proceeded by whatever the xml processor
program likes. Ant treats this like a default xml namespace.
One solution to this (common) problem would be to allow the a's addFileset method
to be matched by both a's namespace fileset element and by ant's default namespace,
so the following would be correct xml:


<a:a>
 <ant:fileset dir="."/>  <!-- matches A.addFileSet() method -->
</a:a>

and
<a:a>
 <a:fileset dir="."/>  <!-- also matches A.addFileSet() method -->
</a:a>

I assume you are refering to A.addFileSet(o.a.t.a.types.FileSet fs) above.

One could conceive of A.addFileSet(com.astuff.FileSet fs) too for custom fileset implementations. A might even have both methods. In this case it seems ant should match different methods. It seems that this should be theroetically possible but, the issue is what happens when ant runs into

<project xmlns:a="antlib:net.a">
<a:a>
 <fileset dir="."/>
<a:a/>
</project>

I think this has to be equivalent to your first example above and

<project>
<a xmlns="antlib:net.a">
 <fileset dir="."/>
<a/>
</project>

must be equivalent to your second example right?


On a side - issue, I think that this solution would help in the uptake of antlibs.

ForExample,
a a build file using ant-contrib with ant 1.5 would look like something
like this:

<project default="compile">
 <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
   <switch value="${foo}">
   <case value="bar">
     <echo message="The value of property foo is bar" />
   </case>
   <case value="baz">
      <echo message="The value of property foo is baz" />
   </case>
   <default>
     <echo message="The value of property foo is not sensible" />
   </default>
 </switch>
</project>

Using antlib:net.sf.antcontrib namespace in ant 1.6 results in 2/3 lines being changed, and one feels like an xml ns lawyer :-( Using the more relaxed rules only involves modifing a couple of lines
and looks (IMO) a lot nicer:


<project default="compile" xmlns:ac="antlib:net.sf.antcontrib">
 <ac:switch value="${foo}">
   <case value="bar">
     <echo message="The value of property foo is bar" />
   </case>
   <case value="baz">
      <echo message="The value of property foo is baz" />
   </case>
   <default>
     <echo message="The value of property foo is not sensible" />
   </default>
 </ac:switch>
</project>

What this xml says to me (and I suspect says to the parser) is that ac:switch is using ant:case elements. If the result is otherwise this doesn't seem to follow the principal of least supprise. (imho)

One could be explicit and only change 1/3 the lines by using:

<project default="compile" xmlns:ant="antlib:org.apache.tools.ant">
<switch value="${foo}" xmlns="antlib:net.sf.antcontrib">
  <case value="bar">
    <ant:echo message="The value of property foo is bar" />
  </case>
  <case value="baz">
     <ant:echo message="The value of property foo is baz" />
  </case>
  <default>
    <ant:echo message="The value of property foo is not sensible" />
  </default>
</ac:switch>
</project>

However, in real use switch probably does more than just echo on each line and so this is of limited help.

Unless I am confused, in your example ant would wind up looking for ant:case, and when it didn't find it it would have to poll the containing elements for their name spaces and search those name spaces or just search all available name spaces for a matching element. (the latter of which obviously runs into problems).

If we do take a shortcut I think it would be better to do it like this:

<project default="compile">
<switch value="${foo}" xmlns="antlib:net.sf.antcontrib">
  <case value="bar">
    <echo message="The value of property foo is bar" />
  </case>
  <case value="baz">
     <echo message="The value of property foo is baz" />
  </case>
  <default>
    <echo message="The value of property foo is not sensible" />
  </default>
</ac:switch>
</project>

This version means that ant looks for an echo element in the antcontrib name space. Upon not finding an ant contrib echo it only has to look in ant core for an alternate echo element and if it doesn't have either an antcontrib echo or an ant echo, it should fail. Basically what we have here is the condition that all antlibs inherit (but may overide) ant core tasks.

I like that one better, what do you think?

Gus

Peter

Gus Heck wrote:

Gus Heck wrote:


re given to the elements in the calling macro.

In ant 1.6.0+, the namespace of elements discovered by reflection take
the namespace uri of type/task that contains the element (Note this is the
uri and not the localname).


The enclosed patch will allow the namespace of nested elements to be
either the ant uri or the namespace of the containing type/task.

I am quite possibly confused but I thought xml namespaces required that the namespace be

1. The namespace indicated by the specified prefix

2. If there is no prefix, then the current default namespace must be used. (defined on some containing element, be it the top element or some other containing element with an xmlns="some uri").

If an unprefixed element is taking on a namespace not declared with xmlns="some uri" (which is different from xmlns:foo="some uri") aren't we blowing it in implementing namespaces correctly?

-Gus

Was I wrong? Confused? or just ignored?

-Gus


--------------------------------------------------------------------- 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]





---------------------------------------------------------------------
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]



Reply via email to