jkeyes 2003/06/03 18:11:41 Modified: cli/src/java/org/apache/commons/cli Tag: cli_1_x OptionGroup.java ExclusiveOptionGroup.java AnonymousArgumentImpl.java Options.java InclusiveOptionGroup.java CommandLineParser.java Log: inital work on new OptionGroup support, some tidy up remains added license removed tabs Revision Changes Path No revision No revision 1.8.2.2 +67 -9 jakarta-commons/cli/src/java/org/apache/commons/cli/OptionGroup.java Index: OptionGroup.java =================================================================== RCS file: /home/cvs/jakarta-commons/cli/src/java/org/apache/commons/cli/OptionGroup.java,v retrieving revision 1.8.2.1 retrieving revision 1.8.2.2 diff -u -r1.8.2.1 -r1.8.2.2 --- OptionGroup.java 19 May 2003 20:59:44 -0000 1.8.2.1 +++ OptionGroup.java 4 Jun 2003 01:11:40 -0000 1.8.2.2 @@ -1,16 +1,74 @@ +/* + * $Header$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact [EMAIL PROTECTED] + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>;. + * + */ package org.apache.commons.cli; -import java.util.Set; - /** - * @author jkeyes + * @author John Keyes */ public interface OptionGroup { - Set getOptions(); - boolean containsOption(Option option); - boolean isSelected(); - void setSelected(Option option); - void reset(); - + + boolean hasOption(String name); + + Option getOption(String name); + + void isValid(CommandLine line) throws ParseException; } 1.1.2.2 +176 -84 jakarta-commons/cli/src/java/org/apache/commons/cli/Attic/ExclusiveOptionGroup.java Index: ExclusiveOptionGroup.java =================================================================== RCS file: /home/cvs/jakarta-commons/cli/src/java/org/apache/commons/cli/Attic/ExclusiveOptionGroup.java,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- ExclusiveOptionGroup.java 19 May 2003 20:57:51 -0000 1.1.2.1 +++ ExclusiveOptionGroup.java 4 Jun 2003 01:11:40 -0000 1.1.2.2 @@ -1,101 +1,193 @@ +/* + * $Header$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact [EMAIL PROTECTED] + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>;. + * + */ package org.apache.commons.cli; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +/** + * @author John Keyes + */ public class ExclusiveOptionGroup implements OptionGroup { private Set options = new HashSet(); - private Set incGroups = new HashSet(); - private Option selected = null; - private InclusiveOptionGroup selectedGroup = null; - private boolean mandatory; - - public ExclusiveOptionGroup() { - } - - public ExclusiveOptionGroup( Set options ) { - options.addAll( options ); - } - - public void add( Option option ) { - options.add( option ); - } - - public void add( Set options ) { - options.addAll( options ); - } - public void add(InclusiveOptionGroup group) { - incGroups.add(group); - } - - public Set getOptions() { - return this.options; - } - - public Set getOptionGroups() { - return this.incGroups; - } - - public boolean containsOption( Option option ) { - if(this.options.contains(option)) { - return true; - } - else { - for(Iterator iter = this.incGroups.iterator(); iter.hasNext();) { - OptionGroup group = (OptionGroup) iter.next(); - if (group.containsOption(option)) { - return true; - } - } - } - return false; - } - - public void setSelected( Option option ) { - if (option == null) { - this.selected = null; - this.selectedGroup = null; - } - - if(this.options.contains(option)) { - this.selected = option; - } - else { - for(Iterator iter = this.incGroups.iterator(); iter.hasNext();) { - InclusiveOptionGroup group = (InclusiveOptionGroup) iter.next(); - if (group.containsOption(option)) { - this.selectedGroup = group; - group.setSelected(option); - return; - } - } - } - } + private Set optionGroups = new HashSet(); - public void setSelected( InclusiveOptionGroup group ) { - this.selectedGroup = group; + public void add(Option option) { + this.options.add(option); } - - public boolean isSelected() { - if( this.selectedGroup != null && this.selectedGroup.allSelected()) { - return true; - } - return (selected != null); - } - - public void setMandatory( boolean mandatory ) { - this.mandatory = mandatory; + + public void add(OptionGroup group) { + this.optionGroups.add(group); } - public boolean isMandatory() { - return this.mandatory; + public boolean hasOption(String name) { + + if (name == null) { + return false; + } + + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + Option option = (Option)iter.next(); + + if (name.equals( "-" + option.getName())) { + return true; + } + else if (name.equals( "--" + option.getLongName())) { + return true; + } + } + } + + if (!optionGroups.isEmpty()) { + for (Iterator iter = optionGroups.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + if (group.hasOption(name)) { + return true; + } + } + } + + return false; } - - public void reset() { - //this.selected = null; - this.selectedGroup = null; + + public Option getOption(String name) { + + if (name == null) { + return null; + } + + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + Option option = (Option)iter.next(); + + if (name.equals("-" + option.getName())) { + return option; + } + else if (name.equals("--" + option.getLongName())) { + return option; + } + } + } + + if (!optionGroups.isEmpty()) { + for (Iterator iter = optionGroups.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + if (group.hasOption(name)) { + return group.getOption(name); + } + } + } + + return null; + } + + /** @task return a descriptive message for the case + * when the group is not valid */ + public void isValid(CommandLine cmdLine) + throws ParseException { + + boolean optionFound = false; + + // validate all Options are present + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + Option option = (Option)iter.next(); + + if (cmdLine.hasOption("-" + option.getName())) { + if (optionFound) { + throw new AlreadySelectedException("(5)"); + // return false; + } + optionFound = true; + } + } + } + + // validate all OptionGroups are present + if (!optionGroups.isEmpty()) { + for (Iterator iter = optionGroups.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + boolean valid = true; + + try { + group.isValid(cmdLine); + } + catch (ParseException exp) { + valid = false; + } + + if (valid && optionFound) { + throw new ParseException("option group not valid (1)"); + } + else if (valid) { + optionFound = true; + } + } + } } } 1.1.2.3 +6 -5 jakarta-commons/cli/src/java/org/apache/commons/cli/Attic/AnonymousArgumentImpl.java Index: AnonymousArgumentImpl.java =================================================================== RCS file: /home/cvs/jakarta-commons/cli/src/java/org/apache/commons/cli/Attic/AnonymousArgumentImpl.java,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- AnonymousArgumentImpl.java 24 May 2003 21:54:15 -0000 1.1.2.2 +++ AnonymousArgumentImpl.java 4 Jun 2003 01:11:40 -0000 1.1.2.3 @@ -194,7 +194,8 @@ * Arguments cannot have a name. */ public String getName() { - throw new UnsupportedOperationException("anonymous argument cannot have a name"); + return "name"; + //throw new UnsupportedOperationException("anonymous argument cannot have a name"); } /** @@ -210,6 +211,6 @@ * Arguments cannot have be required. */ public boolean isRequired() { - throw new UnsupportedOperationException("anonymous argument cannot be required (yet)"); + return false; } } 1.19.2.4 +143 -198 jakarta-commons/cli/src/java/org/apache/commons/cli/Options.java Index: Options.java =================================================================== RCS file: /home/cvs/jakarta-commons/cli/src/java/org/apache/commons/cli/Options.java,v retrieving revision 1.19.2.3 retrieving revision 1.19.2.4 diff -u -r1.19.2.3 -r1.19.2.4 --- Options.java 24 May 2003 14:44:43 -0000 1.19.2.3 +++ Options.java 4 Jun 2003 01:11:40 -0000 1.19.2.4 @@ -58,187 +58,28 @@ * <http://www.apache.org/>;. * */ +/* + */ +/* + */ package org.apache.commons.cli; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.Map; import java.util.Set; /** - * An Options instance defines the structure of a command - * line. It can have three types of element, Option, Argument - * or OptionGroup. - * - * @task consolidate the OptionGroup support - * @task consolidate the AnonymousArgument support - * * @author John Keyes */ public class Options { - /** the child Options and Arguments */ - private Map options = new HashMap(); - - /** the required Options and Arguments */ - private Set required = new HashSet(); - - /** the OptionGroups */ - private Set groups = new HashSet(); + Set options = new HashSet(); + Set optionGroups = new HashSet(); /** the AnonymousArgument */ private Argument anonymousArgument; /** - * Adds the specified Option to this definition - * - * @param option - * a command line Option - */ - public void add(Option option) { - if (option instanceof AnonymousArgumentImpl) { - this.anonymousArgument = (Argument) option; - } else if (option.getName() != null) { - if (options.get(option.getName()) != null) { - options.remove(option.getName()); - } - options.put(option.getName(), option); - } else if (option.getLongName() != null) { - if (options.get(option.getLongName()) != null) { - options.remove(option.getLongName()); - } - options.put(option.getLongName(), option); - } - addIfRequired(option); - - } - - /** - * Adds all of the Options in the specified Set to this definition - * - * @param options - * command line Options to be added to this definition - */ - public void addOptions(Set options) { - for (Iterator iter = options.iterator(); iter.hasNext();) { - Option opt = (Option) iter.next(); - add(opt); - addIfRequired(opt); - } - } - - /** - * Registers the specified Option if it is 'required'. - * - * @param option - * the Option to register if it is 'required' - */ - private void addIfRequired(Option option) { - if (option instanceof AnonymousArgumentImpl) { - return; - } - if (option.isRequired()) { - required.add(option); - } - } - - /** - * Removes any Options that have already been added - * and then adds all of the Options in the specified - * Set. - * - * @param options - * command line Options - */ - public void setOptions(Set options) { - this.options.clear(); - addOptions(options); - } - - /** - * Returns the Options that this definition contains. The - * value that is returned is a new object so changes made - * to it do not modify this definition. - * - * @return the Set of command line Options - */ - public Set getOptions() { - return new HashSet(options.values()); - } - - /** - * Return the Option that whose name is the same as the - * specified name. If no Option exists then check for - * the Option whose long name is the same as the specified - * name. If there is still no match, return null. - * - * @param name - * the name of the Option to search for - * - * @return the Option that matches the search criteria, otherwise null - */ - Option getOption(String name) { - Option option = null; - for (Iterator iter = options.keySet().iterator(); - iter.hasNext() && option == null; - ) { - Option currentOption = (Option) options.get(iter.next()); - if (currentOption.getName() != null - && ("-" + currentOption.getName()).equals(name)) { - option = currentOption; - } else if ( - currentOption.getLongName() != null - && ("--" + currentOption.getLongName()).equals(name)) { - option = currentOption; - } - } - return option; - } - - /** - * Return the number of command line options in this definition - * - * @return the number of Options - */ - public int size() { - return this.options.size(); - } - - /** - * Returns the required Options that this definition contains. - * The value that is returned is a new object so changes made - * to it do not modify this definition. - * - * @return the Set of required command line Options - */ - public Set getRequired() { - return new HashSet(required); - } - - /** - * Returns the OptionGroups that this definition contains. - * The value that is returned is a new object so changes made - * to it do not modify this definition. - * - * @return the Set of command line OptionGroups - */ - public Set getOptionGroups() { - return new HashSet(this.groups); - } - - /** - * Adds the specified group to this definition. - * - * @param group - * a command line OptionGroup - */ - public void add(OptionGroup group) { - this.groups.add(group); - addGroupOptions(group); - } - - /** * Returns whether this definition has an AnonymousArgument * specified. * @@ -257,43 +98,147 @@ return this.anonymousArgument; } - /** - * Removes any OptionGroups that have already been added - * and then adds all of the OptionGroups in the specified - * Set. - * - * @param groups - * a Set of OptionGroups - */ - public void setOptionGroups(Set groups) { - this.groups = groups; - for (Iterator iter = groups.iterator(); iter.hasNext();) { - add((OptionGroup) iter.next()); + + public void add(Option option) { + if (option instanceof AnonymousArgumentImpl) { + this.anonymousArgument = (Argument) option; + return; } + options.add(option); } - - /** - * Adds the individual Options from the specified group - * to the options definition. - * - * @task review this behaviour as it corrupts the contract - * for getOptions. - * - * @param group - * an OptionGroup to add to this definition - */ - private void addGroupOptions(OptionGroup group) { - for (Iterator iter = group.getOptions().iterator(); iter.hasNext();) { - add((Option) iter.next()); + + public void add(Set options) { + this.options.addAll(options); + } + + public void add(OptionGroup group) { + optionGroups.add(group); + } + + public boolean hasOption(String name) { + if (name == null) { + return false; + } + + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + Option option = (Option)iter.next(); + + if (option.getName() != null) { + if (name.equals("-" + option.getName())) { + return true; + } + } + if (option.getLongName() != null) { + if (name.equals("--" + option.getLongName())) { + return true; + } + } + } + } + + return false; + } + + public boolean hasArgument(String name) { + return hasOption(name) && getOption(name) instanceof Argument; + } + + public Argument getArgument(String name) { + return (Argument)getOption(name); + } + + public Option getOption(String name) { + if (name == null) { + return null; + } + + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + Option option = (Option)iter.next(); + + if (option.getName() != null) { + if (name.equals("-" + option.getName())) { + return option; + } + } + if (option.getLongName() != null) { + if (name.equals("--" + option.getLongName())) { + return option; + } + } + } + } + + return null; + } + + public void isValid(CommandLine line) throws ParseException { + + ParseException exception = null; + + if (!optionGroups.isEmpty()) { + for (Iterator iter = optionGroups.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + try { + group.isValid(line); + } + catch(ParseException exp) { + exception = exp; + } + } } + + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext(); ) { + Option option = (Option)iter.next(); + if (option.isRequired()) { + if (option.getName() != null) { + if (!line.hasOption("-" + option.getName())) { + exception = new MissingOptionException("(6)"); + } + } + else if (option.getLongName() != null) { + if (!line.hasOption("--" + option.getLongName())) { + exception = new MissingOptionException("(7)"); + } + } - if (group instanceof ExclusiveOptionGroup) { - ExclusiveOptionGroup excGroup = (ExclusiveOptionGroup) group; - for (Iterator iter = excGroup.getOptionGroups().iterator(); - iter.hasNext(); - ) { - addGroupOptions((OptionGroup) iter.next()); + } + } + } + if (exception != null) { + throw exception; + } + } + + public boolean inOptionGroup(String name) { + + if (!optionGroups.isEmpty()) { + for (Iterator iter = optionGroups.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + if (group.hasOption(name)) { + return true; + } + } + } + + return false; + } + + public OptionGroup getOptionGroup(String name) { + if (!optionGroups.isEmpty()) { + for (Iterator iter = optionGroups.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + if (group.hasOption(name)) { + return group; + } } } + + return null; } -} \ No newline at end of file +} 1.1.2.2 +187 -61 jakarta-commons/cli/src/java/org/apache/commons/cli/Attic/InclusiveOptionGroup.java Index: InclusiveOptionGroup.java =================================================================== RCS file: /home/cvs/jakarta-commons/cli/src/java/org/apache/commons/cli/Attic/InclusiveOptionGroup.java,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- InclusiveOptionGroup.java 19 May 2003 20:57:51 -0000 1.1.2.1 +++ InclusiveOptionGroup.java 4 Jun 2003 01:11:41 -0000 1.1.2.2 @@ -1,68 +1,194 @@ +/* + * $Header$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact [EMAIL PROTECTED] + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>;. + * + */ package org.apache.commons.cli; -import java.util.Set; import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +/** + * @author John Keyes + */ public class InclusiveOptionGroup implements OptionGroup { - private Set options = new HashSet(); - private Set selectedGroups= new HashSet(); - private Option selected = null; - private boolean mandatory; - - public InclusiveOptionGroup() { - } - - public InclusiveOptionGroup( Set options ) { - options.addAll( options ); - } - - public void add( Option option ) { - options.add( option ); - } - - public void add( Set options ) { - options.addAll( options ); - } - - public Set getOptions() { - return this.options; - } - - public boolean containsOption( Option option ) { - return this.options.contains( option ); - } - - public void setFound( Option option ) { - options.remove(option); - } - - public boolean allFound() { - return options.isEmpty(); - } - - public void setSelected(Option option){ - this.selectedGroups.add(option); - } - - public boolean allSelected() { - return this.selectedGroups.equals(options); - } - - public boolean isSelected() { - return false; - } - - public void setMandatory( boolean mandatory ) { - this.mandatory = mandatory; - } - - public boolean isMandatory() { - return this.mandatory; - } - - public void reset() { - // this.selected = null; - this.selectedGroups.clear(); - } + private Set options = new HashSet(); + + private Set optionGroups = new HashSet(); + + public void add(Option option) { + this.options.add(option); + } + + public void add(OptionGroup group) { + this.optionGroups.add(group); + } + + public boolean hasOption(String name) { + + if (name == null) { + return false; + } + + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + Option option = (Option)iter.next(); + + if (name.equals("-" + option.getName())) { + return true; + } + else if (name.equals("--" + option.getLongName())) { + return true; + } + } + } + + if (!optionGroups.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + if (group.hasOption(name)) { + return true; + } + } + } + + return false; + } + + public Option getOption(String name) { + + if (name == null) { + return null; + } + + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + Option option = (Option)iter.next(); + + if (name.equals("-" + option.getName())) { + return option; + } + else if (name.equals("--" + option.getLongName())) { + return option; + } + } + } + + if (!optionGroups.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + if (group.hasOption(name)) { + return group.getOption(name); + } + } + } + + return null; + } + + /** @task return a descriptive message for the case + * when the group is not valid */ + public void isValid(CommandLine cmdLine) + throws ParseException { + + ParseException exp = null; + + // validate all Options are present + if (!options.isEmpty()) { + for (Iterator iter = options.iterator(); iter.hasNext();) { + Option option = (Option)iter.next(); + + if (option.getName() != null) { + if (!cmdLine.hasOption("-" + option.getName())) { + exp = new ParseException("(3)"); + } + } + else if (option.getLongName() != null) { + if (!cmdLine.hasOption("--" + option.getLongName())) { + if (exp == null) { + exp = new ParseException("(3)"); + } + } + else { + exp = null; + } + } + } + } + + // validate all OptionGroups are present + if (!optionGroups.isEmpty()) { + for (Iterator iter = optionGroups.iterator(); iter.hasNext();) { + OptionGroup group = (OptionGroup)iter.next(); + + group.isValid(cmdLine); + // reset exp + exp = null; + } + } + + if (exp != null) { + throw exp; + } + + } } 1.6.2.5 +170 -462 jakarta-commons/cli/src/java/org/apache/commons/cli/CommandLineParser.java Index: CommandLineParser.java =================================================================== RCS file: /home/cvs/jakarta-commons/cli/src/java/org/apache/commons/cli/CommandLineParser.java,v retrieving revision 1.6.2.4 retrieving revision 1.6.2.5 diff -u -r1.6.2.4 -r1.6.2.5 --- CommandLineParser.java 25 May 2003 21:18:41 -0000 1.6.2.4 +++ CommandLineParser.java 4 Jun 2003 01:11:41 -0000 1.6.2.5 @@ -58,165 +58,74 @@ * <http://www.apache.org/>;. * */ +/* + */ package org.apache.commons.cli; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; -import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.StringTokenizer; /** - * Parses command line arguments based upon the rules defined - * in the Options that are passed to it. - * * @author John Keyes */ public class CommandLineParser { - /** - * @task investigate whether this can be eliminated - * - * specifies whether to stop parsing at the first unknown - * token - */ - private boolean stopAtUnknown; - - /** a store for all of the options specified in the Options instance */ - private Map cache = new HashMap(11); - - /** a store of the required Options */ - private Set required = new HashSet(); - - /** - * specifies the style of parsing to use, this is currently decided - * when creating the Option cache. If each Option has a single - * character name, then treat the parsing as Posix, otherwise GNU. - */ - private boolean posix = true; - - /** - * @task should this be a method variable rather than - * a member variable? - * - * the Options to be used for the current parse - */ - private Options options = null; - - /** - * the Java properties that were specified on the command line - */ + public static final int POSIX = 1; + public static final int GNU = 2; + private int style = POSIX; private Properties props = new Properties(); - - /** - * Creates a CommandLineParser - */ - public CommandLineParser() { + + public void setStyle(int style) { + this.style = style; } + + public CommandLine parse(Options options, String[] args) + throws UnknownOptionException, MissingValueException, AlreadySelectedException, ParseException { + CommandLineCreator creator = new CommandLineImpl(); + final List tokens = Arrays.asList(args); - /** - * Creates a CommandLineParser that will cease parsing at - * the first unknown token encountered. - * - * @param stopAtUnknown - * stop at the first unknown token - */ - public CommandLineParser(boolean stopAtUnknown) { - this.stopAtUnknown = stopAtUnknown; + CommandLine line = parse(options, tokens.listIterator(), creator); + + options.isValid((CommandLine)creator); + return line; } - - /** - * Parse the specified command line arguments using the - * specified Options and populate the specified CommandLineCreator - * with the results. - * - * @param options - * the Options definition - * - * @param args - * the command line arguments - * - * @param cmdline - * the CommandLineCreator that will populate the CommandLine - * that will be returned - * - * @return the CommandLine populated with the values - * - * @throws UnknownOptionException - * if an option is specoified on the command line that - * is not defined in the Options - * - * @throws MissingValueException - * if an Argument that requires a value does not have one - * specified on the command line - * - * @throws MissingOptionException - * if a required Option is not specified on the command line - * - * @throws AlreadySelectedException - * if more than one Option in an OptionGroup is present on the - * same command line - */ - private CommandLine parse( - Options options, - String[] args, - CommandLineCreator cmdline) - throws UnknownOptionException, - MissingValueException, - MissingOptionException, - AlreadySelectedException { - - this.options = options; - List tokens = Arrays.asList(args); - createOptionCache(options.getOptions()); - - - int index = 0; - for (ListIterator iter = tokens.listIterator(); iter.hasNext();) { - String token = (String) iter.next(); - - if ("--".equals(token)) { + + public CommandLine parse(Options options, ListIterator iter, CommandLineCreator creator) + throws UnknownOptionException, MissingValueException { + while (iter.hasNext()) { + String arg = iter.next().toString(); + + if ("--".equals(arg)) { List trailing = this.processTrailingValues(iter); - cmdline.setUnprocessed(trailing); + creator.setUnprocessed(trailing); } - // java property - else if (token.startsWith("-D") && token.length() > 2) { - processJavaProperty(token); - } - // a simple key - else if (cache.containsKey(token)) { - Option option = (Option) cache.get(token); - - if (option instanceof Argument) { - cmdline.addArgument( - (Argument) option, - processArgument((Argument) option, iter)); - } else { - cmdline.addOption(option); - } - - if (option.hasChildren()) { - processChildOptions(option, args, index, cmdline); - } - recordIfInOptionGroup(options, option); - recordIfMandatory(option); + else if (arg.startsWith("-D") && arg.length() > 2) { + processJavaProperty(arg); + } + else if (options.hasArgument(arg)) { + processArgument(options, iter, creator, arg, null); + } + else if (options.hasOption(arg)) { + processOption(options, iter, creator, arg); + } + else if (options.inOptionGroup(arg)) { + processOptionGroup(options, iter, creator, arg); } - // we need to burst the key (one character at a time) else if ( - posix - && !token.equals("-") - && token.startsWith("-") - && !token.startsWith("--")) { - burst(token, cmdline, iter); - } else if (token.startsWith("-") && !token.equals("-")) { - char[] chars = token.toCharArray(); + this.style == NewCommandLineParser.POSIX + && !arg.equals("-") + && arg.startsWith("-") + && !arg.startsWith("--")) { + burst(options, arg, creator, iter); + } + else if (arg.startsWith("-") && !arg.equals("-")) { + char[] chars = arg.toCharArray(); int findex = -1; for (int i = 0; i < chars.length && findex == -1; i++) { if (!Character.isJavaIdentifierPart(chars[i]) @@ -226,68 +135,42 @@ } String ntoken = - (findex != -1) ? token.substring(0, findex) : ""; + (findex != -1) ? arg.substring(0, findex) : ""; - if (cache.containsKey(ntoken)) { - Argument argument = (Argument) cache.get(ntoken); - - cmdline.addArgument( - argument, - processArgument( - argument, - iter, - token.substring(findex + 1))); - } else { - throw new UnknownOptionException( - "Unknown option {" + token + "}"); + Option option = options.getOption(ntoken); + if (option == null) { + if (options.inOptionGroup(ntoken)) { + OptionGroup group = options.getOptionGroup(arg); + option = group.getOption(arg); + } } - } else if (options.hasAnonymousArgument()) { - iter.previous(); - cmdline.addArgument( - options.getAnonymousArgument(), - processAnonymousValues(iter)); - } else { - throw new UnknownOptionException( - "Unknown option {" + token + "}"); - } - index++; - } - if (!options.getRequired().equals(required)) { - throw new MissingOptionException( - "All of the required arguments have not been supplied"); - } - - for (Iterator iter = options.getOptionGroups().iterator(); - iter.hasNext(); - ) { - OptionGroup group = (OptionGroup) iter.next(); - - if (group instanceof ExclusiveOptionGroup) { - ExclusiveOptionGroup g = (ExclusiveOptionGroup) group; - if (g.isMandatory() && !group.isSelected()) { - throw new MissingOptionException( - "Required Option not present."); + if (option != null) { + if (option instanceof Argument) { + List values = processArgument((Argument)option, iter, arg.substring(findex + 1)); + creator.addArgument((Argument)option, values); + } } - group.setSelected(null); - } else { - InclusiveOptionGroup g = (InclusiveOptionGroup) group; - if (!g.allFound()) { - throw new MissingOptionException("Required inclusive"); + else { + throw new UnknownOptionException("unknown '" + arg + "'"); } } + else if (options.hasAnonymousArgument()) { + iter.previous(); + creator.addArgument( + options.getAnonymousArgument(), + processAnonymousValues(iter)); + } + else { + throw new UnknownOptionException(arg); + } } - cmdline.setProperties(this.props); + + creator.setProperties(this.props); - return (CommandLine) cmdline; + return (CommandLine)creator; } - /** - * Processes the specified token as a Java property - * - * @param token - * the Java property - */ private void processJavaProperty(String token) { int sep = token.indexOf('='); @@ -304,138 +187,104 @@ props.setProperty(key, value); } - /** - * @task no need for the two parse methods, refactor this - * so there is only one - * - * Parse the specified command line arguments using the - * specified Options and populate the specified CommandLineCreator - * with the results. - * - * @param options - * the Options definition - * - * @param args - * the command line arguments - * - * @return the CommandLine populated with the values - * - * @throws UnknownOptionException - * if an option is specoified on the command line that - * is not defined in the Options - * - * @throws MissingValueException - * if an Argument that requires a value does not have one - * specified on the command line - * - * @throws MissingOptionException - * if a required Option is not specified on the command line - * - * @throws AlreadySelectedException - * if more than one Option in an OptionGroup is present on the - * same command line - */ - public CommandLine parse(Options options, String[] args) - throws UnknownOptionException, - MissingValueException, - MissingOptionException, - AlreadySelectedException { - - CommandLineCreator cmdline = new CommandLineImpl(); - parse(options, args, cmdline); - return (CommandLine) cmdline; + private void processOptionGroup( + Options options, + ListIterator iter, + CommandLineCreator creator, + String arg) + throws MissingValueException, UnknownOptionException { + + OptionGroup group = options.getOptionGroup(arg); + Option option = group.getOption(arg); + if (option instanceof Argument) { + List values = processArgument((Argument)option, iter); + creator.addArgument((Argument)option, values); + } + else { + creator.addOption(option); + } + processChildOptions(option, iter, creator); } - /** - * The specified Option has children so process the - * specified command line arguments, from the specified - * index and populate the specified CommandLineCreator with - * the results. - * - * @param option - * the Option that has child Options - * - * @param arguments - * the command line arguments - * - * @param index - * the index where the processing of the command line - * arguments will begin - * - * @param cmdline - * the CommandLineCreator that will record the results - * - * @throws UnknownOptionException - * if an option is specoified on the command line that - * is not defined in the Options - * - * @throws MissingValueException - * if an Argument that requires a value does not have one - * specified on the command line - * - * @throws MissingOptionException - * if a required Option is not specified on the command line - * - * @throws AlreadySelectedException - * if more than one Option in an OptionGroup is present on the - * same command line - */ + private void processOption( + Options options, + ListIterator iter, + CommandLineCreator creator, + String arg) + throws UnknownOptionException, MissingValueException { + + Option option = options.getOption(arg); + creator.addOption(option); + processChildOptions(option, iter, creator); + } + + private void processArgument( + Options options, + ListIterator iter, + CommandLineCreator creator, + String arg, + String value) + throws MissingValueException, UnknownOptionException { + + Argument argument = options.getArgument(arg); + List values = null; + if (value == null || value.length() == 0) { + values = processArgument(argument, iter); + } + else { + values = processArgument(argument, iter, value); + } + creator.addArgument(argument, values); + processChildOptions(argument, iter, creator); + } + + // + // + // + // + private void burst( + Options options, + String token, + CommandLineCreator creator, + ListIterator iter) + throws UnknownOptionException, MissingValueException { + + int tokenLength = token.length(); + + for (int i = 1; i < tokenLength; i++) { + String arg = "-" + String.valueOf(token.charAt(i)); + + if (options.hasArgument(arg)) { + processArgument(options, iter, creator, arg, token.substring(i+1)); + break; + } + else if (options.hasOption(arg)) { + processOption(options, iter, creator, arg); + } + else if (options.inOptionGroup(arg)) { + processOptionGroup(options, iter, creator, arg); + } + else { + throw new UnknownOptionException("Unknown option {" + arg + "}"); + } + } + } + private void processChildOptions( Option option, - String[] arguments, - int index, - CommandLineCreator cmdline) - throws UnknownOptionException, - MissingValueException, - MissingOptionException, - AlreadySelectedException { + ListIterator iter, + CommandLineCreator cmdline) + throws UnknownOptionException, MissingValueException { if (option.getChildren().size() > 0) { Options opts = new Options(); - opts.addOptions(option.getChildren()); + opts.add(option.getChildren()); - String[] args = new String[arguments.length - index - 1]; - System.arraycopy( - arguments, - index + 1, - args, - 0, - arguments.length - index - 1); - parse(opts, args, cmdline); + parse(opts, iter, cmdline); } } - /** - * If the specified Option is a required Option then - * record that it has been processed. - * - * @param option - * the option that is checked to see if it is required - */ - private void recordIfMandatory(Option option) { - if (option.isRequired()) { - required.add(option); - } - } - - /** - * Determine the values for the specified Argument. - * - * @param argument - * the Argument whose values must be determined - * - * @param iter - * an iterator over the command line arguments - * - * @param arg - * the next token in the command line arguments, - * - * @return the list of values for the specified Argument - * - * @throws MissingValueException - * if <code>arg</code> is null or begins with "-" - */ private List processArgument( Argument argument, ListIterator iter, @@ -562,157 +411,6 @@ } /** - * Processes the Options for this parse and creates the - * Option and required Option caches. - * - * @param options - * the Options used for the current parse - */ - private void createOptionCache(Set options) { - cache.clear(); - required.clear(); - - for (Iterator iter = options.iterator(); iter.hasNext();) { - Option option = (Option) iter.next(); - - String name = option.getName(); - if (posix) { - if (name != null && name.length() > 1) { - posix = false; - } - } - cache.put("-" + name, option); - cache.put("--" + option.getLongName(), option); - } - } - - /** - * If the parse is a 'POSIX' one then the token may need - * to be burst i.e. '-abc' is equivalent to '-a', '-b' and - * '-c' if each of these were Options. If '-a' was an - * Argument, then the tokens would be '-a' and 'bc'. - * - * @param token - * the token to burst - * - * @param cmdline - * the CommandLineCreator to populate - * - * @param iter - * the iterator over the command line arguments - * - * @throws UnknownOptionException - * if an option is specoified on the command line that - * is not defined in the Options - * - * @throws MissingValueException - * if an Argument that requires a value does not have one - * specified on the command line - * - * @throws AlreadySelectedException - * if more than one Option in an OptionGroup is present on the - * same command line - */ - private void burst( - String token, - CommandLineCreator cmdline, - ListIterator iter) - throws UnknownOptionException, - MissingValueException, - AlreadySelectedException { - - int tokenLength = token.length(); - - for (int i = 1; i < tokenLength; i++) { - String ch = String.valueOf(token.charAt(i)); - Option option = (Option) cache.get("-" + ch); - - if (option != null) { - if (option instanceof Argument) { - List args = new ArrayList(); - if (token.substring(i + 1).length() == 0) { - cmdline.addArgument( - (Argument) option, - processArgument((Argument) option, iter)); - } else { - cmdline.addArgument( - (Argument) option, - processArgument( - (Argument) option, - iter, - token.substring(i + 1))); - } - recordIfInOptionGroup(this.options, option); - recordIfMandatory(option); - break; - } else if (option instanceof Option) { - cmdline.addOption(option); - recordIfInOptionGroup(this.options, option); - recordIfMandatory(option); - } - } else { - throw new UnknownOptionException("Unknown option {" + ch + "}"); - } - } - } - - /** - * @task review the OptionGroup behaviour - * - * If the specified Option is a member of an OptionGroup then - * record that it has been found. - * - * @param options - * the Options instance - * - * @param option - * the Option that is being tested - * - * @throws AlreadySelectedException - * if the group is an Exclusive one and an Option from that - * group has already been selected. - */ - private void recordIfInOptionGroup(Options options, Option option) - throws AlreadySelectedException { - for (Iterator iter = options.getOptionGroups().iterator(); - iter.hasNext(); - ) { - OptionGroup group = (OptionGroup) iter.next(); - - if (group instanceof ExclusiveOptionGroup) { - if (group.containsOption(option)) { - if (group.isSelected()) { - throw new AlreadySelectedException( - "Option already selected"); - } else { - group.setSelected(option); - } - } - } else if (group instanceof InclusiveOptionGroup) { - ((InclusiveOptionGroup) group).setFound(option); - } - } - - } - - /** - * Return all of the values that have not been processed. - * - * @param iter - * the iterator over the command line arguments - * - * @return the List of the command line arguments that remain - */ - private List processTrailingValues(Iterator iter) { - List args = new ArrayList(); - - while (iter.hasNext()) { - args.add(iter.next()); - } - return args; - } - - /** * All of the values that remain will be added to the anonymous * argument. * @@ -752,4 +450,14 @@ } return str; } -} \ No newline at end of file + + private List processTrailingValues(Iterator iter) { + List args = new ArrayList(); + + while (iter.hasNext()) { + args.add(iter.next()); + } + return args; + } + +}
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]