You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Rob Oxspring <ro...@imapmail.org> on 2003/06/17 15:24:04 UTC

[CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)

I've had a little look into implementing Commands as I described but wasn't sure how I'd get them in without adding spaghetti to the
code.  While looking around I was reminded of a few things that feel slightly wrong and began to wonder whether the model might be
wrong.  I'll outline the problems and then a solution below that seems pretty clean to me.  The pure text UML could be prettier but
I think you'll get the idea if you use a fixed size font. (I hope you don't regret the "bouncing the ideas around" comment too much
John :o) )

OptionImpl vs. CommandImpl.  Although these two types of object share the common feature of appearing on a command line and having a
group of child options, I'm not convinced that one is an extension of the other.  As a result I've struggled to fit Command into the
hierarchy.

Option vs. Argument.  It might be just me but in the command "ant -f file" I've always regarded it as an option -f with an argument
file, whereas the current model would have an argument "-f file".  This has caused me occasional confusion and it seems that it
would sit easier if Argument were able to deal purely with the "file" section and not have to deal with the option's properties.  If
the Argument were able to drop the option properties then it might also be possible to mix Arguments and Commands together.

AnonymousArgument and UnsupportedMethodException.  Again it might be a personal thing but I've always thought of UME as being a bit
of a code smell - to me it says "the object isn't really a subtype of the specifying class but we've put it here anyway, so there".
I think this strengthens the case against Argument implementing Option.

CommandLineParser knows an awful lot.  I've commented before that the internal handling of -D and -- should be optional but the
knowledge of how all the other options behave seems to be encoded in this class too.  There's nothing inherently wrong with that but
it left me thinking it odd that the Option implementations didn't control the behaviour themselves.  It also struck me that the same
would be true of any HelpFormatter built for the current model.


Without boring you with the route my thoughts took, here's the model I came to with a bit of explanation afterwards.

Class Diagram (Inheritance):

Option <-----------+-- Options <---------------+-- ExclusiveOptions
  getDescription() |     parse(...)            |
  isRequired()     |                           +-- InclusiveOptions
  appendUsage(...) |
  validate(...)    +-- ParentOption <----------+-- DefaultOption
  process(...)     |     processParent(...)    |
  canProcess(...)  |     processChildren(...)  +-- CommandOption
  getPrefixes()    |
                   +-- Argument
                   |
                   +-- PropertyOption
                   |     getInstance()
                   |
                   +-- IgnoreOption
                         getInstance()


Class Diagram (Composition):

Argument --------1 ParentOption --------1 Options --------* Option

The first thing to note is that I've separated out the Option interface from the DefaultOption class.  The Option interface has lost
most of its structure enforcing role and gained behaviour specifying instead.  Some new OptionBuilder would build DefaultOption
instances with all the longName / shortName and other properties of the current OptionImpl class.  Similarly a CommandBuilder would
allow CommandOption instances to be built up with preferredName / aliases properties.

Another important point is that Argument is no longer directly related to the DefaultOption.  Instead it is composed of either a
DefaultOption or CommandOption and concentrates purely on the details of the argument.

Options just becomes a generic object for storing a set of options, the Exclusive / Inclusive just specify more restrictive
behaviour as they do presently.

The idea of PropertyOption (-D) and IgnoreOption (--) just dropped out of the structure and means that this standard behaviour can
be treated as any other option and if people have their own plan for a -D option then they simply don't put a PropertyOption
instance in their Options.

After a little experimentation the sensible methods for Option to specify seem to be the following:
getDescription() - used to allow a HelpFormatter to describe any given Option.
appendUsage(...) - allow the option itself to append a usage string to a StringBuffer
validate(...) - validates a CommandLine's use of this Option
isRequired() - presumably used by validate() and appendUsage()
process(...) - takes a ListIterator of arguments and deals with some/all of them.
canProcess(...) - checks that a call to process(...) will succeed.
getPrefixes() - returns the argument prefixes that could indicate this Option can process a given argument.

One of the nice things about this structure is that when somebody wants to extend the system to cope with windows style "/?"
options, or case insensitive commands, they should only need to add a single Option implementation and any Parser and Formatter will
automatically cope.

I've not yet figured out whether a separate AnonymousArgument is needed or if an Argument could exist without a ParentOption but I'm
sure that the UnsupportedMethodException methods would be gone completely whichever route was taken.

So, thoughts? I'm happy to answer questions and help with implementation as time permits but I'll be on holiday from Friday for 10
days so will be offline for a while.

Rob


----- Original Message ----- 
From: "John Keyes" <jb...@mac.com>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Thursday, June 12, 2003 10:18 AM
Subject: Re: [CLI] Support for CVS style command line


> > The "setDisplayCommandAlias(boolean)" is purely hypothetical at the moment, it illustrates
> > the level of control I was planning on offering but is beyond the implementation so far.
> > I haven't tackled Commands and aliases at all but I guess should put my code
> > where my mouth is.  I'll keep you posted on progress.
> Keep bouncing the ideas around anyway.  If you don't get around to implementing it
> at least the knowledge will be archived.
>
> Thanks,
> -John K
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)

Posted by Rob Oxspring <ro...@imapmail.org>.
John,

I see there is a CLI_ROB branch taken from the trunk, presumably this will be the sandbox for the propsal?  Do you want me to post
updates and patches or do you want to get someone to grant commons commit privs to roxspring? - I have basic impls for
OptionBuilder, ArgumentBuilder and CommandLineParser and updated Argument at the moment with more to follow as time allows.  I've
also got thoughts about how to handle switches too but I'll mail about that separately.

Rob

----- Original Message ----- 
From: "Rob Oxspring" <ro...@imapmail.org>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Tuesday, July 01, 2003 1:46 PM
Subject: Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)


> Sounds like a good plan to me.
>
> Rob
>
> ----- Original Message ----- 
> From: "John Keyes" <jb...@mac.com>
> To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
> Sent: Sunday, June 29, 2003 11:10 PM
> Subject: Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)
>
>
> > Rob,
> >
> > I've been looking at your code and I like the structure.  I'm willing
> > to add
> > this to a new branch (so we can synchronize changes) and we can work on
> > it
> > for the next couple of weeks and see how we think things are
> > progressing.
> >
> > I think the first thing we should do is add the tests from the cli_1_x.
> > This will allow us to get the API in place.  By this I mean adding the
> > XXXBuilder classes and the CommandLineParser class.
> >
> > Let me know what you think and I'll get the ball rolling,
> > -John K
> >


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)

Posted by Rob Oxspring <ro...@imapmail.org>.
Sounds like a good plan to me.

Rob

----- Original Message ----- 
From: "John Keyes" <jb...@mac.com>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Sunday, June 29, 2003 11:10 PM
Subject: Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)


> Rob,
> 
> I've been looking at your code and I like the structure.  I'm willing  
> to add
> this to a new branch (so we can synchronize changes) and we can work on  
> it
> for the next couple of weeks and see how we think things are  
> progressing.
> 
> I think the first thing we should do is add the tests from the cli_1_x.
> This will allow us to get the API in place.  By this I mean adding the
> XXXBuilder classes and the CommandLineParser class.
> 
> Let me know what you think and I'll get the ball rolling,
> -John K
> 
> On Friday, Jun 20, 2003, at 00:27 Europe/Dublin, Rob Oxspring wrote:
> 
> > ----- Original Message -----
> > From: "John Keyes" <jb...@mac.com>
> > To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
> > Sent: Wednesday, June 18, 2003 10:21 PM
> > Subject: Re: [CLI] Do we have the correct model? (was Re: [CLI]  
> > Support for CVS style command line)
> >
> >
> >> Hi Rob,
> >>
> >> <snip/>
> >>
> >>> (I hope you don't regret the "bouncing the ideas around" comment too
> >>> much
> >>> John :o) )
> >>
> >> Is it too late to take it back ;)
> >>
> >>> OptionImpl vs. CommandImpl.  Although these two types of object share
> >>> the common feature of appearing on a command line and having a group
> >>> of child options, I'm not convinced that one is an extension of the
> >>> other.  As a result I've struggled to fit Command into the hierarchy.
> >>
> >> I've been struggling to find a clean entry point as well.  It might be
> >> the case that it cannot be done.
> >>
> >>> Option vs. Argument.  It might be just me but in the command "ant -f
> >>> file" I've always regarded it as an option -f with an argument file,
> >>> whereas the current model would have an argument "-f file".  This has
> >>> caused me occasional confusion and it seems that it
> >>> would sit easier if Argument were able to deal purely with the "file"
> >>> section and not have to deal with the option's properties.  If the
> >>> Argument were able to drop the option properties then it might also  
> >>> be
> >>> possible to mix Arguments and Commands together.
> >>
> >> I've always treated it as '-f file', and never thought of it in any
> >> other manner
> >> as the value is so tightly coupled to the option.  Correct me if my
> >> understanding
> >> is off but is this was you are suggesting, '-f file' is represented by
> >> an Option
> >> that holds a reference to an Argument.
> >
> > Not sure if I'm helping to clear things up but here goes.  I would  
> > regard "-f" as an option, and therefore when faced with "-f file" I  
> > see an option "-f" with an argument "file".  Thinking more though,  
> > this seems like a bit of a bikeshed.  Having an Option that references  
> > an Argument is probably the closest to my description above but the  
> > proposal takes the opposite approach where the Argument wraps a  
> > (Parent)Option.  This means that the Argument object concerns itself  
> > with processing the "file" section but in effect could be considered  
> > the complete "-f file".
> >
> >>
> >>> AnonymousArgument and UnsupportedMethodException.  Again it might be  
> >>> a
> >>> personal thing but I've always thought of UME as being a bit of a  
> >>> code
> >>> smell - to me it says "the object isn't really a subtype of the
> >>> specifying class but we've put it here anyway, so there".  I think
> >>> this strengthens the case against Argument implementing Option.
> >>
> >> The AnonymousArgument feature has not been designed, it has been
> >> *fitted* to the
> >> current implementation.  I think there are places where UME's are
> >> appropriate
> >> (partial implementations of specifications for example), but I too
> >> dislike the
> >> UMEs in AnonymousArgument.  I suspect I was trying to limit the number
> >> of public
> >> types used to 2 (Option and Argument), which I think is obvious from
> >> the impl.
> >
> > Yeah - thats all fair enough.  The "code smell" talk was definitely  
> > the OO purest in me, in reality UME is a useful compromising tool.
> >
> >>
> >>> CommandLineParser knows an awful lot.  I've commented before that the
> >>> internal handling of -D and -- should be optional but the knowledge  
> >>> of
> >>> how all the other options behave seems to be encoded in this class
> >>> too.  There's nothing inherently wrong with that but
> >>> it left me thinking it odd that the Option implementations didn't
> >>> control the behaviour themselves.  It also struck me that the same
> >>> would be true of any HelpFormatter built for the current model.
> >>
> >> I was working on simplifying CommandLineParser last night and I was
> >> thinking
> >> about the validation step (now that it is a separate call) and it
> >> struck me
> >> that the validation and a HelpFormatter would follow the same path
> >> through
> >> the Options instance and that there should be a means to plug-in the
> >> functionality you require, rather than having a separate help() method
> >> being defined on the Option as well.
> >
> > So the "print the usage" and "validate the command line" methods  
> > should use the same code path?  Hmm, I'll have to ponder that.
> >
> >>
> >> I do think the parsing is slighty different, but I need to think about
> >> it in
> >> a bit more detail.  It is possible that with your new proposal, it
> >> works out
> >> fine.
> >>
> >>> Without boring you with the route my thoughts took, here's the model  
> >>> I
> >>> came to with a bit of explanation afterwards.
> >>>
> >>> Class Diagram (Inheritance):
> >>>
> >>> Option <-----------+-- Options <---------------+-- ExclusiveOptions
> >>>   getDescription() |     parse(...)            |
> >>>   isRequired()     |                           +-- InclusiveOptions
> >>>   appendUsage(...) |
> >>>   validate(...)    +-- ParentOption <----------+-- DefaultOption
> >>>   process(...)     |     processParent(...)    |
> >>>   canProcess(...)  |     processChildren(...)  +-- CommandOption
> >>>   getPrefixes()    |
> >>>                    +-- Argument
> >>>                    |
> >>>                    +-- PropertyOption
> >>>                    |     getInstance()
> >>>                    |
> >>>                    +-- IgnoreOption
> >>>                          getInstance()
> >>
> >> Can you explain how Options inherits from Option?  I don't understand
> >> that piece.
> >
> > The proposed Option is a slightly higher level concept than the  
> > current Option.   In the first version of my diagram it was  
> > "CommandLineElement" but this suggested that Options should be called  
> > "CommandLineElements" and the names of all the other classes just  
> > seemed uglier and uglier.  So in the proposal an Option is considered  
> > a generic term for anything that could appear in the command line  
> > structure.  The useful part is that, just like awt's  
> > Component/Container relationship, an Options instance can be treated  
> > just like any other Option but has the facility of holding other  
> > Option instances.
> >
> >>
> >>> Class Diagram (Composition):
> >>>
> >>> Argument --------1 ParentOption --------1 Options --------* Option
> >>
> >> Options == childOptions here?
> >
> > Yes.  An argument "-f file" delegates the processing of "-f" to a  
> > ParentOption.  A ParentOption delegates the processing of any child  
> > options to an Options instance. And the Options class delegates  
> > further processing to one of its Option instances.
> >
> >>
> >>> The first thing to note is that I've separated out the Option
> >>> interface from the DefaultOption class.  The Option interface has  
> >>> lost
> >>> most of its structure enforcing role and gained behaviour specifying
> >>> instead.  Some new OptionBuilder would build DefaultOption instances
> >>> with all the longName / shortName and other properties of the current
> >>> OptionImpl class.  Similarly a CommandBuilder would allow
> >>> CommandOption instances to be built up with preferredName / aliases
> >>> properties.
> >>>
> >>> Another important point is that Argument is no longer directly  
> >>> related
> >>> to the DefaultOption.  Instead it is composed of either a
> >>> DefaultOption or CommandOption and concentrates purely on the details
> >>> of the argument.
> >>>
> >>> Options just becomes a generic object for storing a set of options,
> >>> the Exclusive / Inclusive just specify more restrictive behaviour as
> >>> they do presently.
> >>>
> >>> The idea of PropertyOption (-D) and IgnoreOption (--) just dropped  
> >>> out
> >>> of the structure and means that this standard behaviour can be  
> >>> treated
> >>> as any other option and if people have their own plan for a -D option
> >>> then they simply don't put a PropertyOption
> >>> instance in their Options.
> >>
> >> That makes sense.  I would rename IgnoreOption to ConsumeOption to
> >> signify that
> >> it actually does do something rather than simply ignores the values on
> >> the
> >> command line.
> >
> > +1  I'm not in the running for any class naming awards.
> >
> >>
> >>> After a little experimentation the sensible methods for Option to
> >>> specify seem to be the following:
> >>> getDescription() - used to allow a HelpFormatter to describe any  
> >>> given
> >>> Option.
> >>> appendUsage(...) - allow the option itself to append a usage string  
> >>> to
> >>> a StringBuffer
> >>
> >> I don't fully understand the reason for appendUsage, why would there
> >> not simply
> >> be a getUsage?
> >
> > Thats just my personal habit - I tend to have some sort of  
> > append(StringBuffer) method and then have toString() make use of it,  
> > getUsage() would probably be better than the toString() though.  The  
> > important point is that the Option instance itself becomes responsible  
> > for producing the usage text.
> >
> >>
> >>> validate(...) - validates a CommandLine's use of this Option
> >>> isRequired() - presumably used by validate() and appendUsage()
> >>> process(...) - takes a ListIterator of arguments and deals with
> >>> some/all of them.
> >>> canProcess(...) - checks that a call to process(...) will succeed.
> >>
> >> Is this necessary?  The current impl has two phases, one is to build  
> >> the
> >> CommandLine and the other is to validate the CommandLine against the
> >> Options.
> >
> > Currently the parser has a loop with an if statement:
> > for each argument
> >     if argument=="--" process --
> >     if argumetn "-D" processProperty
> >     if argument begins "-" processOption
> >
> >
> > But because all options become the same, the equivelent section (now  
> > within Options) becomes:
> >
> > for each argument
> >     for each option
> >         if option canProcess argument
> >             option.process
> >
> >>
> >>> getPrefixes() - returns the argument prefixes that could indicate  
> >>> this
> >>> Option can process a given argument.
> >>
> >> Can you explain this in more detail?
> >
> > After several attempts to start I'm tempted to say no!
> >
> > Right. Firstly, it may well be unimportant for now as it is really an  
> > implementation detail of my experimental code - there may be other  
> > stratergies for processing.
> >
> > The idea is that each option will return the set of string prefixes  
> > that this option can handle.  This unifies long and short option names  
> > {-?, -h, --help} along with command names and aliases {update, upd,  
> > up} into a common structure that should make lookups easier.  In the  
> > case of Opions, the set of prefixes is the union of the child options'  
> > prefixes.
> >
> > The canProcess method becomes a trivial case of "return  
> > getPrefixes().contains(arg);" and the Options implementation can use a  
> > prefix->option map to lookup the option to hand off processing to.  Of  
> > course both of these become more complicated as allowances are made  
> > for option bursting and arguments of the style "--arg=val1,val2".
> >
> > I've attached my experimental code in the hope that it'll help you  
> > understand what I mean.  I have options, commands, bursting, option  
> > groups and arguments parsing in isolation but haven't had the chance  
> > to check that combinations work.
> >
> >>
> >>> One of the nice things about this structure is that when somebody
> >>> wants to extend the system to cope with windows style "/?" options,  
> >>> or
> >>> case insensitive commands, they should only need to add a single
> >>> Option implementation and any Parser and Formatter will automatically
> >>> cope.
> >>
> >> Weird!  I had just began looking into this last night.  I removed the
> >> references
> >> to "-" and replaced it with a reference to a static (PREFIX).
> >
> > Yeah that'd work too!
> >>
> >>> I've not yet figured out whether a separate AnonymousArgument is
> >>> needed or if an Argument could exist without a ParentOption but I'm
> >>> sure that the UnsupportedMethodException methods would be gone
> >>> completely whichever route was taken.
> >>
> >> Based on the approach that Option no longer enforces the structure, it
> >> will
> >> follow that there will be no NMEs (depending on what getPrefixes  
> >> does).
> >
> > I'd suggest Collections.EMPTY_SET if getPrefixes() doesn't apply.
> >
> >>
> >>> So, thoughts? I'm happy to answer questions and help with
> >>> implementation as time permits but I'll be on holiday from Friday for
> >>> 10 days so will be offline for a while.
> >>
> >> Well I think I've enough thoughts in there for you ;)
> >
> > Hope all that helps,
> >
> > Rob
> >
> >>
> >> Cheers for the great input,
> >> -John K
> >>
> >>>
> >>> Rob
> >>>
> >>>
> >>> ----- Original Message -----
> >>> From: "John Keyes" <jb...@mac.com>
> >>> To: "Jakarta Commons Developers List"  
> >>> <co...@jakarta.apache.org>
> >>> Sent: Thursday, June 12, 2003 10:18 AM
> >>> Subject: Re: [CLI] Support for CVS style command line
> >>>
> >>>
> >>>>> The "setDisplayCommandAlias(boolean)" is purely hypothetical at the
> >>>>> moment, it illustrates
> >>>>> the level of control I was planning on offering but is beyond the
> >>>>> implementation so far.
> >>>>> I haven't tackled Commands and aliases at all but I guess should  
> >>>>> put
> >>>>> my code
> >>>>> where my mouth is.  I'll keep you posted on progress.
> >>>> Keep bouncing the ideas around anyway.  If you don't get around to
> >>>> implementing it
> >>>> at least the knowledge will be archived.
> >>>>
> >>>> Thanks,
> >>>> -John K
> >>>>
> >>>>
> >>>> -------------------------------------------------------------------- 
> >>>> -
> >>>> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> >>>> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> >>>>
> >>>>
> >>>>
> >>>
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> >>> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> >>>
> >>>
> >> - - - - - - - - - - - - - - - - - - - - - - -
> >> Jakarta Commons CLI
> >> http://jakarta.apache.org/commons/cli
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> >> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> >>
> >>
> >>
> > <clirob.zip>----------------------------------------------------------- 
> > ----------
> > To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> - - - - - - - - - - - - - - - - - - - - - - -
> Jakarta Commons CLI
> http://jakarta.apache.org/commons/cli
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> 
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)

Posted by John Keyes <jb...@mac.com>.
Rob,

I've been looking at your code and I like the structure.  I'm willing  
to add
this to a new branch (so we can synchronize changes) and we can work on  
it
for the next couple of weeks and see how we think things are  
progressing.

I think the first thing we should do is add the tests from the cli_1_x.
This will allow us to get the API in place.  By this I mean adding the
XXXBuilder classes and the CommandLineParser class.

Let me know what you think and I'll get the ball rolling,
-John K

On Friday, Jun 20, 2003, at 00:27 Europe/Dublin, Rob Oxspring wrote:

> ----- Original Message -----
> From: "John Keyes" <jb...@mac.com>
> To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
> Sent: Wednesday, June 18, 2003 10:21 PM
> Subject: Re: [CLI] Do we have the correct model? (was Re: [CLI]  
> Support for CVS style command line)
>
>
>> Hi Rob,
>>
>> <snip/>
>>
>>> (I hope you don't regret the "bouncing the ideas around" comment too
>>> much
>>> John :o) )
>>
>> Is it too late to take it back ;)
>>
>>> OptionImpl vs. CommandImpl.  Although these two types of object share
>>> the common feature of appearing on a command line and having a group
>>> of child options, I'm not convinced that one is an extension of the
>>> other.  As a result I've struggled to fit Command into the hierarchy.
>>
>> I've been struggling to find a clean entry point as well.  It might be
>> the case that it cannot be done.
>>
>>> Option vs. Argument.  It might be just me but in the command "ant -f
>>> file" I've always regarded it as an option -f with an argument file,
>>> whereas the current model would have an argument "-f file".  This has
>>> caused me occasional confusion and it seems that it
>>> would sit easier if Argument were able to deal purely with the "file"
>>> section and not have to deal with the option's properties.  If the
>>> Argument were able to drop the option properties then it might also  
>>> be
>>> possible to mix Arguments and Commands together.
>>
>> I've always treated it as '-f file', and never thought of it in any
>> other manner
>> as the value is so tightly coupled to the option.  Correct me if my
>> understanding
>> is off but is this was you are suggesting, '-f file' is represented by
>> an Option
>> that holds a reference to an Argument.
>
> Not sure if I'm helping to clear things up but here goes.  I would  
> regard "-f" as an option, and therefore when faced with "-f file" I  
> see an option "-f" with an argument "file".  Thinking more though,  
> this seems like a bit of a bikeshed.  Having an Option that references  
> an Argument is probably the closest to my description above but the  
> proposal takes the opposite approach where the Argument wraps a  
> (Parent)Option.  This means that the Argument object concerns itself  
> with processing the "file" section but in effect could be considered  
> the complete "-f file".
>
>>
>>> AnonymousArgument and UnsupportedMethodException.  Again it might be  
>>> a
>>> personal thing but I've always thought of UME as being a bit of a  
>>> code
>>> smell - to me it says "the object isn't really a subtype of the
>>> specifying class but we've put it here anyway, so there".  I think
>>> this strengthens the case against Argument implementing Option.
>>
>> The AnonymousArgument feature has not been designed, it has been
>> *fitted* to the
>> current implementation.  I think there are places where UME's are
>> appropriate
>> (partial implementations of specifications for example), but I too
>> dislike the
>> UMEs in AnonymousArgument.  I suspect I was trying to limit the number
>> of public
>> types used to 2 (Option and Argument), which I think is obvious from
>> the impl.
>
> Yeah - thats all fair enough.  The "code smell" talk was definitely  
> the OO purest in me, in reality UME is a useful compromising tool.
>
>>
>>> CommandLineParser knows an awful lot.  I've commented before that the
>>> internal handling of -D and -- should be optional but the knowledge  
>>> of
>>> how all the other options behave seems to be encoded in this class
>>> too.  There's nothing inherently wrong with that but
>>> it left me thinking it odd that the Option implementations didn't
>>> control the behaviour themselves.  It also struck me that the same
>>> would be true of any HelpFormatter built for the current model.
>>
>> I was working on simplifying CommandLineParser last night and I was
>> thinking
>> about the validation step (now that it is a separate call) and it
>> struck me
>> that the validation and a HelpFormatter would follow the same path
>> through
>> the Options instance and that there should be a means to plug-in the
>> functionality you require, rather than having a separate help() method
>> being defined on the Option as well.
>
> So the "print the usage" and "validate the command line" methods  
> should use the same code path?  Hmm, I'll have to ponder that.
>
>>
>> I do think the parsing is slighty different, but I need to think about
>> it in
>> a bit more detail.  It is possible that with your new proposal, it
>> works out
>> fine.
>>
>>> Without boring you with the route my thoughts took, here's the model  
>>> I
>>> came to with a bit of explanation afterwards.
>>>
>>> Class Diagram (Inheritance):
>>>
>>> Option <-----------+-- Options <---------------+-- ExclusiveOptions
>>>   getDescription() |     parse(...)            |
>>>   isRequired()     |                           +-- InclusiveOptions
>>>   appendUsage(...) |
>>>   validate(...)    +-- ParentOption <----------+-- DefaultOption
>>>   process(...)     |     processParent(...)    |
>>>   canProcess(...)  |     processChildren(...)  +-- CommandOption
>>>   getPrefixes()    |
>>>                    +-- Argument
>>>                    |
>>>                    +-- PropertyOption
>>>                    |     getInstance()
>>>                    |
>>>                    +-- IgnoreOption
>>>                          getInstance()
>>
>> Can you explain how Options inherits from Option?  I don't understand
>> that piece.
>
> The proposed Option is a slightly higher level concept than the  
> current Option.   In the first version of my diagram it was  
> "CommandLineElement" but this suggested that Options should be called  
> "CommandLineElements" and the names of all the other classes just  
> seemed uglier and uglier.  So in the proposal an Option is considered  
> a generic term for anything that could appear in the command line  
> structure.  The useful part is that, just like awt's  
> Component/Container relationship, an Options instance can be treated  
> just like any other Option but has the facility of holding other  
> Option instances.
>
>>
>>> Class Diagram (Composition):
>>>
>>> Argument --------1 ParentOption --------1 Options --------* Option
>>
>> Options == childOptions here?
>
> Yes.  An argument "-f file" delegates the processing of "-f" to a  
> ParentOption.  A ParentOption delegates the processing of any child  
> options to an Options instance. And the Options class delegates  
> further processing to one of its Option instances.
>
>>
>>> The first thing to note is that I've separated out the Option
>>> interface from the DefaultOption class.  The Option interface has  
>>> lost
>>> most of its structure enforcing role and gained behaviour specifying
>>> instead.  Some new OptionBuilder would build DefaultOption instances
>>> with all the longName / shortName and other properties of the current
>>> OptionImpl class.  Similarly a CommandBuilder would allow
>>> CommandOption instances to be built up with preferredName / aliases
>>> properties.
>>>
>>> Another important point is that Argument is no longer directly  
>>> related
>>> to the DefaultOption.  Instead it is composed of either a
>>> DefaultOption or CommandOption and concentrates purely on the details
>>> of the argument.
>>>
>>> Options just becomes a generic object for storing a set of options,
>>> the Exclusive / Inclusive just specify more restrictive behaviour as
>>> they do presently.
>>>
>>> The idea of PropertyOption (-D) and IgnoreOption (--) just dropped  
>>> out
>>> of the structure and means that this standard behaviour can be  
>>> treated
>>> as any other option and if people have their own plan for a -D option
>>> then they simply don't put a PropertyOption
>>> instance in their Options.
>>
>> That makes sense.  I would rename IgnoreOption to ConsumeOption to
>> signify that
>> it actually does do something rather than simply ignores the values on
>> the
>> command line.
>
> +1  I'm not in the running for any class naming awards.
>
>>
>>> After a little experimentation the sensible methods for Option to
>>> specify seem to be the following:
>>> getDescription() - used to allow a HelpFormatter to describe any  
>>> given
>>> Option.
>>> appendUsage(...) - allow the option itself to append a usage string  
>>> to
>>> a StringBuffer
>>
>> I don't fully understand the reason for appendUsage, why would there
>> not simply
>> be a getUsage?
>
> Thats just my personal habit - I tend to have some sort of  
> append(StringBuffer) method and then have toString() make use of it,  
> getUsage() would probably be better than the toString() though.  The  
> important point is that the Option instance itself becomes responsible  
> for producing the usage text.
>
>>
>>> validate(...) - validates a CommandLine's use of this Option
>>> isRequired() - presumably used by validate() and appendUsage()
>>> process(...) - takes a ListIterator of arguments and deals with
>>> some/all of them.
>>> canProcess(...) - checks that a call to process(...) will succeed.
>>
>> Is this necessary?  The current impl has two phases, one is to build  
>> the
>> CommandLine and the other is to validate the CommandLine against the
>> Options.
>
> Currently the parser has a loop with an if statement:
> for each argument
>     if argument=="--" process --
>     if argumetn "-D" processProperty
>     if argument begins "-" processOption
>
>
> But because all options become the same, the equivelent section (now  
> within Options) becomes:
>
> for each argument
>     for each option
>         if option canProcess argument
>             option.process
>
>>
>>> getPrefixes() - returns the argument prefixes that could indicate  
>>> this
>>> Option can process a given argument.
>>
>> Can you explain this in more detail?
>
> After several attempts to start I'm tempted to say no!
>
> Right. Firstly, it may well be unimportant for now as it is really an  
> implementation detail of my experimental code - there may be other  
> stratergies for processing.
>
> The idea is that each option will return the set of string prefixes  
> that this option can handle.  This unifies long and short option names  
> {-?, -h, --help} along with command names and aliases {update, upd,  
> up} into a common structure that should make lookups easier.  In the  
> case of Opions, the set of prefixes is the union of the child options'  
> prefixes.
>
> The canProcess method becomes a trivial case of "return  
> getPrefixes().contains(arg);" and the Options implementation can use a  
> prefix->option map to lookup the option to hand off processing to.  Of  
> course both of these become more complicated as allowances are made  
> for option bursting and arguments of the style "--arg=val1,val2".
>
> I've attached my experimental code in the hope that it'll help you  
> understand what I mean.  I have options, commands, bursting, option  
> groups and arguments parsing in isolation but haven't had the chance  
> to check that combinations work.
>
>>
>>> One of the nice things about this structure is that when somebody
>>> wants to extend the system to cope with windows style "/?" options,  
>>> or
>>> case insensitive commands, they should only need to add a single
>>> Option implementation and any Parser and Formatter will automatically
>>> cope.
>>
>> Weird!  I had just began looking into this last night.  I removed the
>> references
>> to "-" and replaced it with a reference to a static (PREFIX).
>
> Yeah that'd work too!
>>
>>> I've not yet figured out whether a separate AnonymousArgument is
>>> needed or if an Argument could exist without a ParentOption but I'm
>>> sure that the UnsupportedMethodException methods would be gone
>>> completely whichever route was taken.
>>
>> Based on the approach that Option no longer enforces the structure, it
>> will
>> follow that there will be no NMEs (depending on what getPrefixes  
>> does).
>
> I'd suggest Collections.EMPTY_SET if getPrefixes() doesn't apply.
>
>>
>>> So, thoughts? I'm happy to answer questions and help with
>>> implementation as time permits but I'll be on holiday from Friday for
>>> 10 days so will be offline for a while.
>>
>> Well I think I've enough thoughts in there for you ;)
>
> Hope all that helps,
>
> Rob
>
>>
>> Cheers for the great input,
>> -John K
>>
>>>
>>> Rob
>>>
>>>
>>> ----- Original Message -----
>>> From: "John Keyes" <jb...@mac.com>
>>> To: "Jakarta Commons Developers List"  
>>> <co...@jakarta.apache.org>
>>> Sent: Thursday, June 12, 2003 10:18 AM
>>> Subject: Re: [CLI] Support for CVS style command line
>>>
>>>
>>>>> The "setDisplayCommandAlias(boolean)" is purely hypothetical at the
>>>>> moment, it illustrates
>>>>> the level of control I was planning on offering but is beyond the
>>>>> implementation so far.
>>>>> I haven't tackled Commands and aliases at all but I guess should  
>>>>> put
>>>>> my code
>>>>> where my mouth is.  I'll keep you posted on progress.
>>>> Keep bouncing the ideas around anyway.  If you don't get around to
>>>> implementing it
>>>> at least the knowledge will be archived.
>>>>
>>>> Thanks,
>>>> -John K
>>>>
>>>>
>>>> -------------------------------------------------------------------- 
>>>> -
>>>> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
>>>> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>>>>
>>>>
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
>>> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>>>
>>>
>> - - - - - - - - - - - - - - - - - - - - - - -
>> Jakarta Commons CLI
>> http://jakarta.apache.org/commons/cli
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>>
>>
>>
> <clirob.zip>----------------------------------------------------------- 
> ----------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
- - - - - - - - - - - - - - - - - - - - - - -
Jakarta Commons CLI
http://jakarta.apache.org/commons/cli


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)

Posted by Rob Oxspring <ro...@imapmail.org>.
----- Original Message ----- 
From: "John Keyes" <jb...@mac.com>
To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
Sent: Wednesday, June 18, 2003 10:21 PM
Subject: Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)


> Hi Rob,
> 
> <snip/>
> 
> > (I hope you don't regret the "bouncing the ideas around" comment too 
> > much
> > John :o) )
> 
> Is it too late to take it back ;)
> 
> > OptionImpl vs. CommandImpl.  Although these two types of object share 
> > the common feature of appearing on a command line and having a group 
> > of child options, I'm not convinced that one is an extension of the 
> > other.  As a result I've struggled to fit Command into the hierarchy.
> 
> I've been struggling to find a clean entry point as well.  It might be
> the case that it cannot be done.
> 
> > Option vs. Argument.  It might be just me but in the command "ant -f 
> > file" I've always regarded it as an option -f with an argument file, 
> > whereas the current model would have an argument "-f file".  This has 
> > caused me occasional confusion and it seems that it
> > would sit easier if Argument were able to deal purely with the "file" 
> > section and not have to deal with the option's properties.  If the 
> > Argument were able to drop the option properties then it might also be 
> > possible to mix Arguments and Commands together.
> 
> I've always treated it as '-f file', and never thought of it in any 
> other manner
> as the value is so tightly coupled to the option.  Correct me if my 
> understanding
> is off but is this was you are suggesting, '-f file' is represented by 
> an Option
> that holds a reference to an Argument.

Not sure if I'm helping to clear things up but here goes.  I would regard "-f" as an option, and therefore when faced with "-f file" I see an option "-f" with an argument "file".  Thinking more though, this seems like a bit of a bikeshed.  Having an Option that references an Argument is probably the closest to my description above but the proposal takes the opposite approach where the Argument wraps a (Parent)Option.  This means that the Argument object concerns itself with processing the "file" section but in effect could be considered the complete "-f file".

> 
> > AnonymousArgument and UnsupportedMethodException.  Again it might be a 
> > personal thing but I've always thought of UME as being a bit of a code 
> > smell - to me it says "the object isn't really a subtype of the 
> > specifying class but we've put it here anyway, so there".  I think 
> > this strengthens the case against Argument implementing Option.
> 
> The AnonymousArgument feature has not been designed, it has been 
> *fitted* to the
> current implementation.  I think there are places where UME's are 
> appropriate
> (partial implementations of specifications for example), but I too 
> dislike the
> UMEs in AnonymousArgument.  I suspect I was trying to limit the number 
> of public
> types used to 2 (Option and Argument), which I think is obvious from 
> the impl.

Yeah - thats all fair enough.  The "code smell" talk was definitely the OO purest in me, in reality UME is a useful compromising tool.  

> 
> > CommandLineParser knows an awful lot.  I've commented before that the 
> > internal handling of -D and -- should be optional but the knowledge of 
> > how all the other options behave seems to be encoded in this class 
> > too.  There's nothing inherently wrong with that but
> > it left me thinking it odd that the Option implementations didn't 
> > control the behaviour themselves.  It also struck me that the same 
> > would be true of any HelpFormatter built for the current model.
> 
> I was working on simplifying CommandLineParser last night and I was 
> thinking
> about the validation step (now that it is a separate call) and it 
> struck me
> that the validation and a HelpFormatter would follow the same path 
> through
> the Options instance and that there should be a means to plug-in the
> functionality you require, rather than having a separate help() method
> being defined on the Option as well.

So the "print the usage" and "validate the command line" methods should use the same code path?  Hmm, I'll have to ponder that.

> 
> I do think the parsing is slighty different, but I need to think about 
> it in
> a bit more detail.  It is possible that with your new proposal, it 
> works out
> fine.
> 
> > Without boring you with the route my thoughts took, here's the model I 
> > came to with a bit of explanation afterwards.
> >
> > Class Diagram (Inheritance):
> >
> > Option <-----------+-- Options <---------------+-- ExclusiveOptions
> >   getDescription() |     parse(...)            |
> >   isRequired()     |                           +-- InclusiveOptions
> >   appendUsage(...) |
> >   validate(...)    +-- ParentOption <----------+-- DefaultOption
> >   process(...)     |     processParent(...)    |
> >   canProcess(...)  |     processChildren(...)  +-- CommandOption
> >   getPrefixes()    |
> >                    +-- Argument
> >                    |
> >                    +-- PropertyOption
> >                    |     getInstance()
> >                    |
> >                    +-- IgnoreOption
> >                          getInstance()
> 
> Can you explain how Options inherits from Option?  I don't understand
> that piece.

The proposed Option is a slightly higher level concept than the current Option.   In the first version of my diagram it was "CommandLineElement" but this suggested that Options should be called "CommandLineElements" and the names of all the other classes just seemed uglier and uglier.  So in the proposal an Option is considered a generic term for anything that could appear in the command line structure.  The useful part is that, just like awt's Component/Container relationship, an Options instance can be treated just like any other Option but has the facility of holding other Option instances.

> 
> > Class Diagram (Composition):
> >
> > Argument --------1 ParentOption --------1 Options --------* Option
> 
> Options == childOptions here?

Yes.  An argument "-f file" delegates the processing of "-f" to a ParentOption.  A ParentOption delegates the processing of any child options to an Options instance. And the Options class delegates further processing to one of its Option instances.

> 
> > The first thing to note is that I've separated out the Option 
> > interface from the DefaultOption class.  The Option interface has lost 
> > most of its structure enforcing role and gained behaviour specifying 
> > instead.  Some new OptionBuilder would build DefaultOption instances 
> > with all the longName / shortName and other properties of the current 
> > OptionImpl class.  Similarly a CommandBuilder would allow 
> > CommandOption instances to be built up with preferredName / aliases 
> > properties.
> >
> > Another important point is that Argument is no longer directly related 
> > to the DefaultOption.  Instead it is composed of either a 
> > DefaultOption or CommandOption and concentrates purely on the details 
> > of the argument.
> >
> > Options just becomes a generic object for storing a set of options, 
> > the Exclusive / Inclusive just specify more restrictive behaviour as 
> > they do presently.
> >
> > The idea of PropertyOption (-D) and IgnoreOption (--) just dropped out 
> > of the structure and means that this standard behaviour can be treated 
> > as any other option and if people have their own plan for a -D option 
> > then they simply don't put a PropertyOption
> > instance in their Options.
> 
> That makes sense.  I would rename IgnoreOption to ConsumeOption to 
> signify that
> it actually does do something rather than simply ignores the values on 
> the
> command line.

+1  I'm not in the running for any class naming awards.

> 
> > After a little experimentation the sensible methods for Option to 
> > specify seem to be the following:
> > getDescription() - used to allow a HelpFormatter to describe any given 
> > Option.
> > appendUsage(...) - allow the option itself to append a usage string to 
> > a StringBuffer
> 
> I don't fully understand the reason for appendUsage, why would there 
> not simply
> be a getUsage?

Thats just my personal habit - I tend to have some sort of append(StringBuffer) method and then have toString() make use of it, getUsage() would probably be better than the toString() though.  The important point is that the Option instance itself becomes responsible for producing the usage text.

> 
> > validate(...) - validates a CommandLine's use of this Option
> > isRequired() - presumably used by validate() and appendUsage()
> > process(...) - takes a ListIterator of arguments and deals with 
> > some/all of them.
> > canProcess(...) - checks that a call to process(...) will succeed.
> 
> Is this necessary?  The current impl has two phases, one is to build the
> CommandLine and the other is to validate the CommandLine against the 
> Options.

Currently the parser has a loop with an if statement:
for each argument
    if argument=="--" process --
    if argumetn "-D" processProperty
    if argument begins "-" processOption


But because all options become the same, the equivelent section (now within Options) becomes:

for each argument
    for each option
        if option canProcess argument
            option.process

> 
> > getPrefixes() - returns the argument prefixes that could indicate this 
> > Option can process a given argument.
> 
> Can you explain this in more detail?

After several attempts to start I'm tempted to say no!

Right. Firstly, it may well be unimportant for now as it is really an implementation detail of my experimental code - there may be other stratergies for processing.

The idea is that each option will return the set of string prefixes that this option can handle.  This unifies long and short option names {-?, -h, --help} along with command names and aliases {update, upd, up} into a common structure that should make lookups easier.  In the case of Opions, the set of prefixes is the union of the child options' prefixes.

The canProcess method becomes a trivial case of "return getPrefixes().contains(arg);" and the Options implementation can use a prefix->option map to lookup the option to hand off processing to.  Of course both of these become more complicated as allowances are made for option bursting and arguments of the style "--arg=val1,val2".

I've attached my experimental code in the hope that it'll help you understand what I mean.  I have options, commands, bursting, option groups and arguments parsing in isolation but haven't had the chance to check that combinations work.

> 
> > One of the nice things about this structure is that when somebody 
> > wants to extend the system to cope with windows style "/?" options, or 
> > case insensitive commands, they should only need to add a single 
> > Option implementation and any Parser and Formatter will automatically 
> > cope.
> 
> Weird!  I had just began looking into this last night.  I removed the 
> references
> to "-" and replaced it with a reference to a static (PREFIX).

Yeah that'd work too!
> 
> > I've not yet figured out whether a separate AnonymousArgument is 
> > needed or if an Argument could exist without a ParentOption but I'm 
> > sure that the UnsupportedMethodException methods would be gone 
> > completely whichever route was taken.
> 
> Based on the approach that Option no longer enforces the structure, it 
> will
> follow that there will be no NMEs (depending on what getPrefixes does).

I'd suggest Collections.EMPTY_SET if getPrefixes() doesn't apply.

> 
> > So, thoughts? I'm happy to answer questions and help with 
> > implementation as time permits but I'll be on holiday from Friday for 
> > 10 days so will be offline for a while.
> 
> Well I think I've enough thoughts in there for you ;)

Hope all that helps,

Rob

> 
> Cheers for the great input,
> -John K
> 
> >
> > Rob
> >
> >
> > ----- Original Message -----
> > From: "John Keyes" <jb...@mac.com>
> > To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
> > Sent: Thursday, June 12, 2003 10:18 AM
> > Subject: Re: [CLI] Support for CVS style command line
> >
> >
> >>> The "setDisplayCommandAlias(boolean)" is purely hypothetical at the 
> >>> moment, it illustrates
> >>> the level of control I was planning on offering but is beyond the 
> >>> implementation so far.
> >>> I haven't tackled Commands and aliases at all but I guess should put 
> >>> my code
> >>> where my mouth is.  I'll keep you posted on progress.
> >> Keep bouncing the ideas around anyway.  If you don't get around to 
> >> implementing it
> >> at least the knowledge will be archived.
> >>
> >> Thanks,
> >> -John K
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> >> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> >>
> >>
> >>
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> >
> >
> - - - - - - - - - - - - - - - - - - - - - - -
> Jakarta Commons CLI
> http://jakarta.apache.org/commons/cli
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> 
> 
> 

Re: [CLI] Do we have the correct model? (was Re: [CLI] Support for CVS style command line)

Posted by John Keyes <jb...@mac.com>.
Hi Rob,

<snip/>

> (I hope you don't regret the "bouncing the ideas around" comment too 
> much
> John :o) )

Is it too late to take it back ;)

> OptionImpl vs. CommandImpl.  Although these two types of object share 
> the common feature of appearing on a command line and having a group 
> of child options, I'm not convinced that one is an extension of the 
> other.  As a result I've struggled to fit Command into the hierarchy.

I've been struggling to find a clean entry point as well.  It might be
the case that it cannot be done.

> Option vs. Argument.  It might be just me but in the command "ant -f 
> file" I've always regarded it as an option -f with an argument file, 
> whereas the current model would have an argument "-f file".  This has 
> caused me occasional confusion and it seems that it
> would sit easier if Argument were able to deal purely with the "file" 
> section and not have to deal with the option's properties.  If the 
> Argument were able to drop the option properties then it might also be 
> possible to mix Arguments and Commands together.

I've always treated it as '-f file', and never thought of it in any 
other manner
as the value is so tightly coupled to the option.  Correct me if my 
understanding
is off but is this was you are suggesting, '-f file' is represented by 
an Option
that holds a reference to an Argument.

> AnonymousArgument and UnsupportedMethodException.  Again it might be a 
> personal thing but I've always thought of UME as being a bit of a code 
> smell - to me it says "the object isn't really a subtype of the 
> specifying class but we've put it here anyway, so there".  I think 
> this strengthens the case against Argument implementing Option.

The AnonymousArgument feature has not been designed, it has been 
*fitted* to the
current implementation.  I think there are places where UME's are 
appropriate
(partial implementations of specifications for example), but I too 
dislike the
UMEs in AnonymousArgument.  I suspect I was trying to limit the number 
of public
types used to 2 (Option and Argument), which I think is obvious from 
the impl.

> CommandLineParser knows an awful lot.  I've commented before that the 
> internal handling of -D and -- should be optional but the knowledge of 
> how all the other options behave seems to be encoded in this class 
> too.  There's nothing inherently wrong with that but
> it left me thinking it odd that the Option implementations didn't 
> control the behaviour themselves.  It also struck me that the same 
> would be true of any HelpFormatter built for the current model.

I was working on simplifying CommandLineParser last night and I was 
thinking
about the validation step (now that it is a separate call) and it 
struck me
that the validation and a HelpFormatter would follow the same path 
through
the Options instance and that there should be a means to plug-in the
functionality you require, rather than having a separate help() method
being defined on the Option as well.

I do think the parsing is slighty different, but I need to think about 
it in
a bit more detail.  It is possible that with your new proposal, it 
works out
fine.

> Without boring you with the route my thoughts took, here's the model I 
> came to with a bit of explanation afterwards.
>
> Class Diagram (Inheritance):
>
> Option <-----------+-- Options <---------------+-- ExclusiveOptions
>   getDescription() |     parse(...)            |
>   isRequired()     |                           +-- InclusiveOptions
>   appendUsage(...) |
>   validate(...)    +-- ParentOption <----------+-- DefaultOption
>   process(...)     |     processParent(...)    |
>   canProcess(...)  |     processChildren(...)  +-- CommandOption
>   getPrefixes()    |
>                    +-- Argument
>                    |
>                    +-- PropertyOption
>                    |     getInstance()
>                    |
>                    +-- IgnoreOption
>                          getInstance()

Can you explain how Options inherits from Option?  I don't understand
that piece.

> Class Diagram (Composition):
>
> Argument --------1 ParentOption --------1 Options --------* Option

Options == childOptions here?

> The first thing to note is that I've separated out the Option 
> interface from the DefaultOption class.  The Option interface has lost 
> most of its structure enforcing role and gained behaviour specifying 
> instead.  Some new OptionBuilder would build DefaultOption instances 
> with all the longName / shortName and other properties of the current 
> OptionImpl class.  Similarly a CommandBuilder would allow 
> CommandOption instances to be built up with preferredName / aliases 
> properties.
>
> Another important point is that Argument is no longer directly related 
> to the DefaultOption.  Instead it is composed of either a 
> DefaultOption or CommandOption and concentrates purely on the details 
> of the argument.
>
> Options just becomes a generic object for storing a set of options, 
> the Exclusive / Inclusive just specify more restrictive behaviour as 
> they do presently.
>
> The idea of PropertyOption (-D) and IgnoreOption (--) just dropped out 
> of the structure and means that this standard behaviour can be treated 
> as any other option and if people have their own plan for a -D option 
> then they simply don't put a PropertyOption
> instance in their Options.

That makes sense.  I would rename IgnoreOption to ConsumeOption to 
signify that
it actually does do something rather than simply ignores the values on 
the
command line.

> After a little experimentation the sensible methods for Option to 
> specify seem to be the following:
> getDescription() - used to allow a HelpFormatter to describe any given 
> Option.
> appendUsage(...) - allow the option itself to append a usage string to 
> a StringBuffer

I don't fully understand the reason for appendUsage, why would there 
not simply
be a getUsage?

> validate(...) - validates a CommandLine's use of this Option
> isRequired() - presumably used by validate() and appendUsage()
> process(...) - takes a ListIterator of arguments and deals with 
> some/all of them.
> canProcess(...) - checks that a call to process(...) will succeed.

Is this necessary?  The current impl has two phases, one is to build the
CommandLine and the other is to validate the CommandLine against the 
Options.

> getPrefixes() - returns the argument prefixes that could indicate this 
> Option can process a given argument.

Can you explain this in more detail?

> One of the nice things about this structure is that when somebody 
> wants to extend the system to cope with windows style "/?" options, or 
> case insensitive commands, they should only need to add a single 
> Option implementation and any Parser and Formatter will automatically 
> cope.

Weird!  I had just began looking into this last night.  I removed the 
references
to "-" and replaced it with a reference to a static (PREFIX).

> I've not yet figured out whether a separate AnonymousArgument is 
> needed or if an Argument could exist without a ParentOption but I'm 
> sure that the UnsupportedMethodException methods would be gone 
> completely whichever route was taken.

Based on the approach that Option no longer enforces the structure, it 
will
follow that there will be no NMEs (depending on what getPrefixes does).

> So, thoughts? I'm happy to answer questions and help with 
> implementation as time permits but I'll be on holiday from Friday for 
> 10 days so will be offline for a while.

Well I think I've enough thoughts in there for you ;)

Cheers for the great input,
-John K

>
> Rob
>
>
> ----- Original Message -----
> From: "John Keyes" <jb...@mac.com>
> To: "Jakarta Commons Developers List" <co...@jakarta.apache.org>
> Sent: Thursday, June 12, 2003 10:18 AM
> Subject: Re: [CLI] Support for CVS style command line
>
>
>>> The "setDisplayCommandAlias(boolean)" is purely hypothetical at the 
>>> moment, it illustrates
>>> the level of control I was planning on offering but is beyond the 
>>> implementation so far.
>>> I haven't tackled Commands and aliases at all but I guess should put 
>>> my code
>>> where my mouth is.  I'll keep you posted on progress.
>> Keep bouncing the ideas around anyway.  If you don't get around to 
>> implementing it
>> at least the knowledge will be archived.
>>
>> Thanks,
>> -John K
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>>
>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>
>
- - - - - - - - - - - - - - - - - - - - - - -
Jakarta Commons CLI
http://jakarta.apache.org/commons/cli


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org