Author: drew
Date: Wed Jul  7 23:41:46 2010
New Revision: 961538

URL: http://svn.apache.org/viewvc?rev=961538&view=rev
Log:
MAHOUT-404: AbstractJob fixes from 
https://issues.apache.org/jira/secure/attachment/12448373/MAHOUT-404.patch

Added:
    
mahout/trunk/core/src/test/java/org/apache/mahout/common/AbstractJobTest.java
Modified:
    mahout/trunk/core/src/main/java/org/apache/mahout/common/AbstractJob.java

Modified: 
mahout/trunk/core/src/main/java/org/apache/mahout/common/AbstractJob.java
URL: 
http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/common/AbstractJob.java?rev=961538&r1=961537&r2=961538&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/common/AbstractJob.java 
(original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/common/AbstractJob.java 
Wed Jul  7 23:41:46 2010
@@ -124,7 +124,7 @@ public abstract class AbstractJob extend
    * @param description
    */
   protected void addFlag(String name, String shortName, String description) {
-    options.add(buildOption(name, shortName, description, true, false, null));
+    options.add(buildOption(name, shortName, description, false, false, null));
   }
   
   /** Add an option to the the set of options this job will parse when
@@ -280,6 +280,8 @@ public abstract class AbstractJob extend
       parser.setGroup(group);
       parser.setHelpOption(helpOpt);
       cmdLine = parser.parse(args);
+      
+      
     } catch (OptionException e) {
       log.error(e.getMessage());
       CommandLineUtil.printHelpWithGenericOptions(group);
@@ -291,22 +293,39 @@ public abstract class AbstractJob extend
       return null;
     }
     
+    try {
+      parseDirectories(cmdLine);
+    } catch (IllegalArgumentException e) {
+      log.error(e.getMessage());
+      CommandLineUtil.printHelpWithGenericOptions(group);
+      return null;
+    }
+    
+    
     Map<String,String> result = new TreeMap<String,String>();
     maybePut(result, cmdLine, this.options.toArray(new 
Option[this.options.size()]));
 
-    parseDirectories(cmdLine);
-    
     log.info("Command line arguments: {}", result);
     return result;
   }
   
-  /** Extract the values of the <code>inputOption</code> and 
<code>outputOption</code>
-   *  if present, otherwise attempt to retrieve the values of 
<code>mapred.input.dir</code>
-   *  and <code>mapred.output.dir</code>. If none of these are set, 
-   *  {...@link #getInputPath()} and {...@link #getOutputPath()} will return 
null.
+  /** Obtain input and output directories from command-line options or hadoop
+   *  properties. If <code>addInputOption</code> or 
<code>addOutputOption</code>
+   *  has been called, this method will throw an <code>OptionException</code> 
if
+   *  no source (command-line or property) for that value is present. 
+   *  Otherwise, <code>inputPath</code> or <code>outputPath<code> will be 
+   *  non-null only if specified as a hadoop property. Command-line options
+   *  take precedence over hadoop properties.
+   * 
    * @param cmdLine
+   * @throws IllegalArgumentException if either inputOption is present,
+   *   and neither <code>--input</code> nor <code>-Dmapred.input dir</code> 
are 
+   *   specified or outputOption is present and neither <code>--output</code> 
+   *   nor <code>-Dmapred.output.dir</code> are specified.
    */
-  protected void parseDirectories(CommandLine cmdLine) {
+  protected void parseDirectories(CommandLine cmdLine) 
+    throws IllegalArgumentException {
+    
     Configuration conf = getConf();
     
     if (inputOption != null && cmdLine.hasOption(inputOption)) {
@@ -322,14 +341,32 @@ public abstract class AbstractJob extend
     if (outputPath == null && conf.get("mapred.output.dir") != null) {
       this.outputPath = new Path(conf.get("mapred.output.dir"));
     }
+    
+    if (inputOption != null && inputPath == null) {
+      throw new IllegalArgumentException("No input specified: " +
+          inputOption.getPreferredName() + " or -Dmapred.input.dir " +
+          "must be provided to specify input directory");
+    }
+    
+    if (outputOption != null && outputPath == null) {
+      throw new IllegalArgumentException("No output specified: " +
+          outputOption.getPreferredName() + " or -Dmapred.output.dir " +
+          "must be provided to specify output directory");
+    }
   }
   
   protected static void maybePut(Map<String,String> args, CommandLine cmdLine, 
Option... opt) {
     for (Option o : opt) {
-      // nulls are ok, for cases where options are simple flags.
-      Object vo = cmdLine.getValue(o);
-      String value = (vo == null) ? null : vo.toString();
-      args.put(o.getPreferredName(), value);
+      
+      // the option appeared on the command-line, or it has a value
+      // (which is likely a default value). 
+      if (cmdLine.hasOption(o) || cmdLine.getValue(o) != null) {
+        
+        // nulls are ok, for cases where options are simple flags.
+        Object vo = cmdLine.getValue(o);
+        String value = (vo == null) ? null : vo.toString();
+        args.put(o.getPreferredName(), value);
+      }
     }
   }
 

Added: 
mahout/trunk/core/src/test/java/org/apache/mahout/common/AbstractJobTest.java
URL: 
http://svn.apache.org/viewvc/mahout/trunk/core/src/test/java/org/apache/mahout/common/AbstractJobTest.java?rev=961538&view=auto
==============================================================================
--- 
mahout/trunk/core/src/test/java/org/apache/mahout/common/AbstractJobTest.java 
(added)
+++ 
mahout/trunk/core/src/test/java/org/apache/mahout/common/AbstractJobTest.java 
Wed Jul  7 23:41:46 2010
@@ -0,0 +1,254 @@
+/**
+ * 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.mahout.common;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.util.ToolRunner;
+import org.apache.mahout.common.commandline.DefaultOptionCreator;
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+/**
+ * 
+ */
+public class AbstractJobTest {
+  
+  interface AbstractJobFactory {
+    public AbstractJob getJob();
+  }
+  
+  @Test
+  public void testFlag() throws Exception {
+    final Map<String,String> testMap = new HashMap<String,String>();
+    
+    final AbstractJobFactory fact = new AbstractJobFactory() {
+      public AbstractJob getJob() {
+        return new AbstractJob() {
+          @Override
+          public int run(String[] args) throws Exception {
+            addFlag("testFlag", "t", "a simple test flag");
+            
+            Map<String,String> argMap = parseArguments(args);
+            testMap.clear();
+            testMap.putAll(argMap);
+            return 1;
+          }
+        };
+      }
+    };
+    
+    // testFlag will only be present if speciied on the command-line
+    
+    String[] noFlag   = new String[0];
+    ToolRunner.run(fact.getJob(), noFlag);
+    TestCase.assertFalse("test map for absent flag",
+        testMap.containsKey("--testFlag"));
+    
+    String[] withFlag = { "--testFlag" };
+    ToolRunner.run(fact.getJob(), withFlag);
+    TestCase.assertTrue("test map for present flag",
+        testMap.containsKey("--testFlag"));
+  }
+  
+  @Test
+  public void testOptions() throws Exception {
+    final Map<String,String> testMap = new HashMap<String,String>();
+    
+    final AbstractJobFactory fact = new AbstractJobFactory() {
+      public AbstractJob getJob() {
+        return new AbstractJob() {
+          @Override
+          public int run(String[] args) throws Exception {
+            this.addOption(DefaultOptionCreator.overwriteOption().create());
+            this.addOption("option", "o", "option");
+            this.addOption("required", "r", "required", true /* required */);
+            this.addOption("notRequired", "nr", "not required", false /* not 
required */);
+            this.addOption("hasDefault", "hd", "option w/ default", 
"defaultValue");
+            
+            
+            Map<String,String> argMap = parseArguments(args);
+            if (argMap == null) {
+              return -1;
+            }
+            
+            testMap.clear();
+            testMap.putAll(argMap);
+
+            return 0;
+          }
+        };
+      }
+    };
+    
+    int ret;
+    
+    ret = ToolRunner.run(fact.getJob(), new String[0]);
+    TestCase.assertEquals("-1 for missing required options", -1, ret);
+    
+    ret = ToolRunner.run(fact.getJob(), new String[]{
+      "--required", "requiredArg"
+    });
+    TestCase.assertEquals("0 for no missing required options", 0, ret);
+    TestCase.assertEquals("requiredArg", testMap.get("--required"));
+    TestCase.assertEquals("defaultValue", testMap.get("--hasDefault"));
+    TestCase.assertNull(testMap.get("--option"));
+    TestCase.assertNull(testMap.get("--notRequired"));
+    TestCase.assertFalse(testMap.containsKey("--overwrite"));
+    
+    ret = ToolRunner.run(fact.getJob(), new String[]{
+      "--required", "requiredArg",
+      "--unknownArg"
+    });
+    TestCase.assertEquals("-1 for including unknown options", -1, ret);
+
+    ret = ToolRunner.run(fact.getJob(), new String[]{
+      "--required", "requiredArg",
+      "--required", "requiredArg2",
+    });
+    TestCase.assertEquals("-1 for including duplicate options", -1, ret);
+    
+    ret = ToolRunner.run(fact.getJob(), new String[]{
+      "--required", "requiredArg", 
+      "--overwrite",
+      "--hasDefault", "nonDefault",
+      "--option", "optionValue",
+      "--notRequired", "notRequired"
+    });
+    TestCase.assertEquals("0 for no missing required options", 0, ret);
+    TestCase.assertEquals("requiredArg", testMap.get("--required"));
+    TestCase.assertEquals("nonDefault", testMap.get("--hasDefault"));
+    TestCase.assertEquals("optionValue", testMap.get("--option"));
+    TestCase.assertEquals("notRequired", testMap.get("--notRequired"));
+    TestCase.assertTrue(testMap.containsKey("--overwrite"));
+    
+    ret = ToolRunner.run(fact.getJob(), new String[]{
+      "-r", "requiredArg", 
+      "-ow",
+      "-hd", "nonDefault",
+      "-o", "optionValue",
+      "-nr", "notRequired"
+    });
+    TestCase.assertEquals("0 for no missing required options", 0, ret);
+    TestCase.assertEquals("requiredArg", testMap.get("--required"));
+    TestCase.assertEquals("nonDefault", testMap.get("--hasDefault"));
+    TestCase.assertEquals("optionValue", testMap.get("--option"));
+    TestCase.assertEquals("notRequired", testMap.get("--notRequired"));
+    TestCase.assertTrue(testMap.containsKey("--overwrite"));
+    
+  }
+  
+  @Test
+  public void testInputOutputPaths() throws Exception {
+    
+    final AbstractJobFactory fact = new AbstractJobFactory() {
+      public AbstractJob getJob() {
+        return new AbstractJob() {
+          @Override
+          public int run(String[] args) throws Exception {
+            addInputOption();
+            addOutputOption();
+            
+            // arg map should be null if a required option is missing.
+            Map<String, String> argMap = parseArguments(args);
+            
+            if (argMap == null) {
+              return -1;
+            }
+            
+            Path inputPath = getInputPath();
+            TestCase.assertNotNull("getInputPath() returns non-null", 
inputPath);
+            
+            Path outputPath = getInputPath();
+            TestCase.assertNotNull("getOutputPath() returns non-null", 
outputPath);
+            return 0;
+          }
+        };
+      }
+    };
+    
+    AbstractJob job;
+    int ret;
+    
+    ret = ToolRunner.run(fact.getJob(), new String[0]);
+    TestCase.assertEquals("-1 for missing input option", -1, ret);
+    
+    final String testInputPath = "testInputPath";
+    final String testOutputPath = "testOutputPath";
+    final String testInputPropertyPath = "testInputPropertyPath";
+    final String testOutputPropertyPath = "testOutputPropertyPath";
+    
+    job = fact.getJob();
+    ret = ToolRunner.run(job, new String[]{ 
+        "--input", testInputPath });
+    TestCase.assertEquals("-1 for missing output option", -1, ret);
+    TestCase.assertEquals("input path is correct", testInputPath, 
+        job.getInputPath().toString());
+    
+    job = fact.getJob();
+    ret = ToolRunner.run(job, new String[]{ 
+        "--output", testOutputPath });
+    TestCase.assertEquals("-1 for missing input option", -1, ret);
+    TestCase.assertEquals("output path is correct", testOutputPath, 
+        job.getOutputPath().toString());
+    
+    job = fact.getJob();
+    ret = ToolRunner.run(job, new String[]{ 
+        "--input", testInputPath, "--output", testOutputPath });
+    TestCase.assertEquals("0 for complete options", 0, ret);
+    TestCase.assertEquals("input path is correct", testInputPath, 
+        job.getInputPath().toString());
+    TestCase.assertEquals("output path is correct", testOutputPath, 
+        job.getOutputPath().toString());
+    
+    job = fact.getJob();
+    ret = ToolRunner.run(job, new String[]{ 
+        "--input", testInputPath, "--output", testOutputPath });
+    TestCase.assertEquals("0 for complete options", 0, ret);
+    TestCase.assertEquals("input path is correct", testInputPath, 
+        job.getInputPath().toString());
+    TestCase.assertEquals("output path is correct", testOutputPath, 
+        job.getOutputPath().toString());
+    
+    job = fact.getJob();
+    ret = ToolRunner.run(job, new String[]{ 
+        "-Dmapred.input.dir=" + testInputPropertyPath, 
+        "-Dmapred.output.dir=" + testOutputPropertyPath });
+    TestCase.assertEquals("0 for complete options", 0, ret);
+    TestCase.assertEquals("input path from property is correct", 
+        testInputPropertyPath, job.getInputPath().toString());
+    TestCase.assertEquals("output path from property is correct", 
+        testOutputPropertyPath, job.getOutputPath().toString());
+    
+    job = fact.getJob();
+    ret = ToolRunner.run(job, new String[]{ 
+        "-Dmapred.input.dir=" + testInputPropertyPath,
+        "-Dmapred.output.dir=" + testOutputPropertyPath,
+        "--input", testInputPath,
+        "--output", testOutputPath });
+    TestCase.assertEquals("input command-line option precedes property", 
+        testInputPath, job.getInputPath().toString());
+    TestCase.assertEquals("output command-line option precedes property", 
+        testOutputPath, job.getOutputPath().toString());
+       }
+}


Reply via email to