ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From William Uther <will+...@cs.cmu.edu>
Subject Re: Tasks containing other tasks (was: Subtasks within tasks)
Date Fri, 25 Feb 2000 05:23:40 GMT
> I have few problems with that particular solution:

Ok.  Thanks for the comments.  I think you must have misunderstood my
intent though, or else I've misunderstood your reply.  I've re-ordered your
mail in my reply to try to clear that up.

> - What is a sub task anyway ? I can't figure what it will do. SubCopy? 

A subtask is just a task contained within another task.  Any task could be
a sub-task.  It is just like a property, except that you will not know its
name at compile-time, so you cannot have a createXxxx() method.  My patch
allows you to use any task in the system as a property.  It does this NOT
by marking out the tasks that can be sub-tasks (you could do this
currently) but by marking out the tasks/property-objects that can contain
other tasks as sub-tasks.

I should have named the 'SubTaskable' interface 'TaskContainer'.  (Just
made that name change in my code).  The addSubTask() method should probably
be named addTask(), but I thought that would conflict with the attribute
addXxx() methods.  What do you think?

Having a generic TaskContainer capability allows you to create tasks such
as:

<switch name="os.name">
	<case value="Mac OS">
		<javac ..... />
	</case>
	<case value="Win*">
		<javac ..... />
	</case>
	<deafult>
		<Deltree ..... />
	</default>
</switch>

This couldn't be made under the current ANT unless you specifically added a
createJavac() method to the Case class.  Using my code, the Case class
implements TaskContainer.

In detail; when ProjectHelper encounters the first <javac .... /> above, it
looks for a Case.createJavac() method, but none exists.  It then looks to
see if Case implements TaskContainer.  It does, so ProjectHelper creates a
new javac task and calls Case.addSubTask() with the new javac object.

Another example of a task requiring subtasks (Although this is not
currently possible because of the strange semantics of task
creation/execution):

<ForEach variable="i" list="subprojectA:subprojectB" separator=":">
	<Ant dir="${i}" target="clean" />
	<Ant dir="${i}" target="main" />
</ForEach>

> - it is specific to Tasks ( createSubTask, SubTaskable, etc ) - everything
> else in ant is using introspection and patterns.

You can view it as a generalization of the way that Targets currently work.
They do NOT use introspection.  They use a single addTask(Task) method.  No
introspection neccessary.  Nor do I think introspection should be used
where another simple solution exists.  Introspection moves errors from
compile-time to run-time, something I prefer to avoid.

> - it sound a bit to complex 

Implementation or use?

It is simpler than your suggestion in both respects.

> If you have a particular task that needs this kind of sub-task we should
> try to find a pattern-based solution.
> 
> In particular addXXX works fine in this case and doesn't require any
> interface ( and it's implemented in tomcat ):

I don't understand how you use a generic addXxx methods in this case.  You
really only need one method corresponding to addTask()/addSubTask().

> For "<foo>":
> 
> - first try createFoo() 
> - if no such method is found, try to create a foo object ( based on 
> existing taskdefs )
> - try addFoo( foo ) 
> - if no such method try addBar() where Bar is an interface implemented by
> foo ( or superclass).

Why not just use addTask( foo )?  You're making this more complex than it
needs to be.

Given there is only one method needed, why do you prefer reflection over an
interface?

I originially implemented this using reflection to check for the method.
The interface solution is much cleaner.  It adds compile-time type
checking.  It also makes the code self-documenting.  (You know instantly
which tasks can handle sub-tasks because they implement TaskContainer.  You
don't have to search for methods with a particular pattern.)

> Each "try" is just a getMethod() and check if not null, and it's very
> easy. I think the pattern makes sense and in tomcat seems to work fine
> ( addServerConnector() with AjpConnector, HttpConnector, etc ).

Why didn't you use this for Targets?

As I said, I think I just wasn't clear enough about what the patch did.
Hopefully I was clearer in this email.

\x/ill             :-}


Mime
View raw message