Author: ebourg
Date: Tue May 26 11:48:44 2009
New Revision: 778664

URL: http://svn.apache.org/viewvc?rev=778664&view=rev
Log:
Implemented the partial matching for long options in the PosixParser (CLI-160)

Added:
    
commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java
   (with props)
Modified:
    commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java
    commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java
    commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java
    
commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java
    commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java
    commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java
    commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java
    commons/proper/cli/trunk/xdocs/changes.xml

Added: 
commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java?rev=778664&view=auto
==============================================================================
--- 
commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java
 (added)
+++ 
commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java
 Tue May 26 11:48:44 2009
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.cli;
+
+import java.util.Collection;
+
+/**
+ * Exception thrown when an option can't be identified from a partial name.
+ * 
+ * @author Emmanuel Bourg
+ * @version $Revision$, $Date$
+ * @since 1.3
+ */
+public class AmbiguousOptionException extends UnrecognizedOptionException
+{
+    /** The list of options matching the partial name specified */
+    private Collection matchingOptions;
+
+    /**
+     * Constructs a new AmbiguousOptionException.
+     *
+     * @param option          the partial option name
+     * @param matchingOptions the options matching the name
+     */
+    public AmbiguousOptionException(String option, Collection matchingOptions)
+    {
+        super("Ambiguous option: " + option, option);
+        this.matchingOptions = matchingOptions;
+    }
+
+    /**
+     * Returns the options matching the partial name.
+     */
+    public Collection getMatchingOptions()
+    {
+        return matchingOptions;
+    }
+}

Propchange: 
commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java?rev=778664&r1=778663&r2=778664&view=diff
==============================================================================
--- commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java 
(original)
+++ commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java Tue 
May 26 11:48:44 2009
@@ -214,6 +214,32 @@
     }
 
     /**
+     * Returns the options with a long name starting with the name specified.
+     * 
+     * @param opt the partial name of the option
+     * @return the options matching the partial name specified, or an empty 
list if none matches
+     * @since 1.3
+     */
+    public List getMatchingOptions(String opt)
+    {
+        opt = Util.stripLeadingHyphens(opt);
+        
+        List matchingOpts = new ArrayList();
+        
+        Iterator it = longOpts.keySet().iterator();
+        while (it.hasNext())
+        {
+            String longOpt = (String) it.next();
+            if (longOpt.startsWith(opt))
+            {
+                matchingOpts.add(longOpt);
+            }
+        }        
+        
+        return matchingOpts;
+    }
+
+    /**
      * Returns whether the named {...@link Option} is a member of this 
{...@link Options}.
      *
      * @param opt short or long name of the {...@link Option}

Modified: commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java?rev=778664&r1=778663&r2=778664&view=diff
==============================================================================
--- commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java 
(original)
+++ commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java Tue 
May 26 11:48:44 2009
@@ -68,7 +68,7 @@
      * flattening when a non option has been encountered
      * @return a String array of the flattened arguments
      */
-    protected abstract String[] flatten(Options opts, String[] arguments, 
boolean stopAtNonOption);
+    protected abstract String[] flatten(Options opts, String[] arguments, 
boolean stopAtNonOption) throws ParseException;
 
     /**
      * Parses the specified <code>arguments</code> based

Modified: 
commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java?rev=778664&r1=778663&r2=778664&view=diff
==============================================================================
--- commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java 
(original)
+++ commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java 
Tue May 26 11:48:44 2009
@@ -92,7 +92,7 @@
      * when an non option is found.
      * @return The flattened <code>arguments</code> String array.
      */
-    protected String[] flatten(Options options, String[] arguments, boolean 
stopAtNonOption)
+    protected String[] flatten(Options options, String[] arguments, boolean 
stopAtNonOption) throws ParseException
     {
         init();
         this.options = options;
@@ -106,21 +106,33 @@
             // get the next command line token
             String token = (String) iter.next();
 
+            // single or double hyphen
+            if ("-".equals(token) || "--".equals(token))
+            {
+                tokens.add(token);
+            }
+            
             // handle long option --foo or --foo=bar
-            if (token.startsWith("--"))
+            else if (token.startsWith("--"))
             {
                 int pos = token.indexOf('=');
                 String opt = pos == -1 ? token : token.substring(0, pos); // 
--foo
+                
+                List matchingOpts = options.getMatchingOptions(opt);
 
-                if (!options.hasOption(opt))
+                if (matchingOpts.isEmpty())
                 {
                     processNonOptionToken(token, stopAtNonOption);
                 }
+                else if (matchingOpts.size() > 1)
+                {
+                    throw new AmbiguousOptionException(opt, matchingOpts);
+                }
                 else
                 {
-                    currentOption = options.getOption(opt);
+                    currentOption = options.getOption((String) 
matchingOpts.get(0));
                     
-                    tokens.add(opt);
+                    tokens.add("--" + currentOption.getLongOpt());
                     if (pos != -1)
                     {
                         tokens.add(token.substring(pos + 1));
@@ -128,17 +140,25 @@
                 }
             }
 
-            // single hyphen
-            else if ("-".equals(token))
-            {
-                tokens.add(token);
-            }
             else if (token.startsWith("-"))
             {
                 if (token.length() == 2 || options.hasOption(token))
                 {
                     processOptionToken(token, stopAtNonOption);
                 }
+                else if (!options.getMatchingOptions(token).isEmpty())
+                {
+                    List matchingOpts = options.getMatchingOptions(token);
+                    if (matchingOpts.size() > 1)
+                    {
+                        throw new AmbiguousOptionException(token, 
matchingOpts);
+                    }
+                    else
+                    {
+                        Option opt = options.getOption((String) 
matchingOpts.get(0));
+                        processOptionToken("-" + opt.getLongOpt(), 
stopAtNonOption);
+                    }
+                }
                 // requires bursting
                 else
                 {

Modified: 
commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java?rev=778664&r1=778663&r2=778664&view=diff
==============================================================================
--- 
commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java 
(original)
+++ 
commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java 
Tue May 26 11:48:44 2009
@@ -53,4 +53,29 @@
     {
         // not supported by the BasicParser
     }
+    
+    public void testUnambiguousPartialLongOption1() throws Exception
+    {
+        // not supported by the BasicParser
+    }
+
+    public void testUnambiguousPartialLongOption2() throws Exception
+    {
+        // not supported by the BasicParser
+    }
+
+    public void testAmbiguousPartialLongOption1() throws Exception
+    {
+        // not supported by the BasicParser
+    }
+
+    public void testAmbiguousPartialLongOption2() throws Exception
+    {
+        // not supported by the BasicParser
+    }
+
+    public void testPartialLongOptionWithShort() throws Exception
+    {
+        // not supported by the BasicParser
+    }
 }

Modified: 
commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java?rev=778664&r1=778663&r2=778664&view=diff
==============================================================================
--- commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java 
(original)
+++ commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java 
Tue May 26 11:48:44 2009
@@ -24,4 +24,29 @@
         super.setUp();
         parser = new GnuParser();
     }
+
+    public void testUnambiguousPartialLongOption1() throws Exception
+    {
+        // not supported by the GnuParser
+    }
+
+    public void testUnambiguousPartialLongOption2() throws Exception
+    {
+        // not supported by the GnuParser
+    }
+
+    public void testAmbiguousPartialLongOption1() throws Exception
+    {
+        // not supported by the GnuParser
+    }
+
+    public void testAmbiguousPartialLongOption2() throws Exception
+    {
+        // not supported by the GnuParser
+    }
+
+    public void testPartialLongOptionWithShort() throws Exception
+    {
+        // not supported by the GnuParser
+    }
 }

Modified: 
commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java?rev=778664&r1=778663&r2=778664&view=diff
==============================================================================
--- commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java 
(original)
+++ commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java 
Tue May 26 11:48:44 2009
@@ -159,4 +159,15 @@
         assertNotNull(options.getOptionGroups());
         assertEquals(2, options.getOptionGroups().size());
     }
+    
+    public void testGetMatchingOpts()
+    {
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("version").create());
+        options.addOption(OptionBuilder.withLongOpt("verbose").create());
+        
+        assertTrue(options.getMatchingOptions("foo").isEmpty());
+        assertEquals(1, options.getMatchingOptions("version").size());
+        assertEquals(2, options.getMatchingOptions("ver").size());
+    }
 }

Modified: 
commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java?rev=778664&r1=778663&r2=778664&view=diff
==============================================================================
--- 
commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java 
(original)
+++ 
commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java 
Tue May 26 11:48:44 2009
@@ -303,4 +303,94 @@
         assertEquals("Should be 1 arg left",1,argsleft.size());
         assertEquals("Expecting foo","foo",argsleft.get(0));
     }
+    
+    public void testUnambiguousPartialLongOption1() throws Exception
+    {
+        String[] args = new String[] { "--ver" };
+        
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("version").create());
+        options.addOption(OptionBuilder.withLongOpt("help").create());
+        
+        CommandLine cl = parser.parse(options, args);
+        
+        assertTrue("Confirm --version is set", cl.hasOption("version"));
+    }
+
+    public void testUnambiguousPartialLongOption2() throws Exception
+    {
+        String[] args = new String[] { "-ver" };
+        
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("version").create());
+        options.addOption(OptionBuilder.withLongOpt("help").create());
+        
+        CommandLine cl = parser.parse(options, args);
+        
+        assertTrue("Confirm --version is set", cl.hasOption("version"));
+    }
+
+    public void testAmbiguousPartialLongOption1() throws Exception
+    {
+        String[] args = new String[] { "--ver" };
+        
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("version").create());
+        options.addOption(OptionBuilder.withLongOpt("verbose").create());
+        
+        boolean caught = false;
+        
+        try 
+        {
+            parser.parse(options, args);
+        }
+        catch (AmbiguousOptionException e) 
+        {
+            caught = true;
+            assertEquals("Partial option", "--ver", e.getOption());
+            assertNotNull("Matching options null", e.getMatchingOptions());
+            assertEquals("Matching options size", 2, 
e.getMatchingOptions().size());
+        }
+        
+        assertTrue( "Confirm MissingArgumentException caught", caught );
+    }
+    
+    public void testAmbiguousPartialLongOption2() throws Exception
+    {
+        String[] args = new String[] { "-ver" };
+        
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("version").create());
+        options.addOption(OptionBuilder.withLongOpt("verbose").create());
+        
+        boolean caught = false;
+        
+        try 
+        {
+            parser.parse(options, args);
+        }
+        catch (AmbiguousOptionException e) 
+        {
+            caught = true;
+            assertEquals("Partial option", "-ver", e.getOption());
+            assertNotNull("Matching options null", e.getMatchingOptions());
+            assertEquals("Matching options size", 2, 
e.getMatchingOptions().size());
+        }
+        
+        assertTrue( "Confirm MissingArgumentException caught", caught );
+    }
+    
+    public void testPartialLongOptionWithShort() throws Exception
+    {
+        String[] args = new String[] { "-ver" };
+        
+        Options options = new Options();
+        options.addOption(OptionBuilder.withLongOpt("version").create());
+        options.addOption(OptionBuilder.hasArg().create('v'));
+        
+        CommandLine cl = parser.parse(options, args);
+        
+        assertTrue("Confirm --version is set", cl.hasOption("version"));
+        assertTrue("Confirm -v is not set", !cl.hasOption("v"));
+    }
 }

Modified: commons/proper/cli/trunk/xdocs/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/cli/trunk/xdocs/changes.xml?rev=778664&r1=778663&r2=778664&view=diff
==============================================================================
--- commons/proper/cli/trunk/xdocs/changes.xml (original)
+++ commons/proper/cli/trunk/xdocs/changes.xml Tue May 26 11:48:44 2009
@@ -21,6 +21,12 @@
     <title>Commons CLI Release Notes</title>
   </properties>
   <body>
+    
+    <release version="1.3" date="in SVN">
+      <action type="add" dev="ebourg" issue="CLI-160">
+        PosixParser now supports partial long options (--ver instead of 
--version)
+      </action>
+    </release>
 
     <release version="1.2" date="2009-03-19" description="This is a 
maintenance release containing bug fixes.">
       <action type="fix" dev="oheger" issue="CLI-175">
@@ -38,9 +44,6 @@
       <action type="fix" dev="bayard" issue="CLI-170">
         TypeHandler prints messages to stderr.
       </action>
-      <action type="fix" dev="bayard" issue="CLI-170">
-        TypeHandler prints messages to stderr.
-      </action>
       <action type="fix" dev="bayard" issue="CLI-162">
         Infinite loop in the wrapping code of HelpFormatter.
       </action>


Reply via email to