You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sqoop.apache.org by ab...@apache.org on 2014/10/03 08:53:16 UTC

[02/13] SQOOP-1498: Sqoop2: Repository Object refactoring (objects prefixed with M)

http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigDisplayer.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigDisplayer.java b/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigDisplayer.java
new file mode 100644
index 0000000..dea271a
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigDisplayer.java
@@ -0,0 +1,258 @@
+/**
+ * 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.sqoop.shell.utils;
+
+import static org.apache.sqoop.shell.ShellEnvironment.print;
+import static org.apache.sqoop.shell.ShellEnvironment.println;
+import static org.apache.sqoop.shell.ShellEnvironment.resourceString;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sqoop.common.Direction;
+import org.apache.sqoop.model.MAccountableEntity;
+import org.apache.sqoop.model.MBooleanInput;
+import org.apache.sqoop.model.MConfig;
+import org.apache.sqoop.model.MConnector;
+import org.apache.sqoop.model.MDriverConfig;
+import org.apache.sqoop.model.MEnumInput;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MInputType;
+import org.apache.sqoop.model.MIntegerInput;
+import org.apache.sqoop.model.MJob;
+import org.apache.sqoop.model.MLink;
+import org.apache.sqoop.model.MMapInput;
+import org.apache.sqoop.model.MStringInput;
+import org.apache.sqoop.shell.core.Constants;
+import org.apache.sqoop.validation.Message;
+import org.apache.sqoop.validation.Status;
+
+/**
+ * Convenience static methods for displaying config related information
+ */
+public final class ConfigDisplayer {
+
+  public static void displayDriverConfigDetails(MDriverConfig driverConfig, ResourceBundle bundle) {
+    displayConfig(driverConfig.getConfigs(),
+        resourceString(Constants.RES_CONFIG_DISPLAYER_JOB), bundle);
+  }
+
+  public static void displayConnectorConfigDetails(MConnector connector, ResourceBundle bundle) {
+    displayConfig(
+        connector.getLinkConfig().getConfigs(),
+        resourceString(Constants.RES_CONFIG_DISPLAYER_LINK),
+        bundle);
+
+    displayConfig(
+        connector.getConfig(Direction.FROM).getConfigs(),
+        Direction.FROM.toString() + " " + resourceString(Constants.RES_CONFIG_DISPLAYER_JOB),
+        bundle);
+
+    displayConfig(
+        connector.getConfig(Direction.TO).getConfigs(),
+        Direction.TO.toString() + " " + resourceString(Constants.RES_CONFIG_DISPLAYER_JOB),
+        bundle);
+  }
+
+   private static void displayConfig(List<MConfig> configs,
+                                         String type,
+                                         ResourceBundle bundle) {
+    Iterator<MConfig> iterator = configs.iterator();
+    int findx = 1;
+    while (iterator.hasNext()) {
+      print("    ");
+      print(type);
+      print(" %s ", resourceString(Constants.RES_CONFIG_DISPLAYER_CONFIG));
+      print(findx++);
+      println(":");
+
+      MConfig config = iterator.next();
+      print("      %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_NAME));
+      println(config.getName());
+
+      // Label
+      print("      %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_LABEL));
+      println(bundle.getString(config.getLabelKey()));
+
+      // Help text
+      print("      %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_HELP));
+      println(bundle.getString(config.getHelpKey()));
+
+      List<MInput<?>> inputs = config.getInputs();
+      Iterator<MInput<?>> iiter = inputs.iterator();
+      int iindx = 1;
+      while (iiter.hasNext()) {
+        print("      %s ", resourceString(Constants.RES_CONFIG_DISPLAYER_INPUT));
+        print(iindx++);
+        println(":");
+
+        MInput<?> input = iiter.next();
+        print("        %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_NAME));
+        println(input.getName());
+        print("        %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_LABEL));
+        println(bundle.getString(input.getLabelKey()));
+        print("        %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_HELP));
+        println(bundle.getString(input.getHelpKey()));
+        print("        %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_TYPE));
+        println(input.getType());
+        print("        %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_SENSITIVE));
+        println(input.isSensitive());
+        if (input.getType() == MInputType.STRING) {
+          print("        %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_SIZE));
+          println(((MStringInput)input).getMaxLength());
+        } else if(input.getType() == MInputType.ENUM) {
+          print("        %s: ", resourceString(Constants.RES_CONFIG_DISPLAYER_POSSIBLE_VALUES));
+          println(StringUtils.join(((MEnumInput)input).getValues(), ","));
+        }
+      }
+    }
+  }
+
+  public static void displayConfig(List<MConfig> configs, ResourceBundle bundle) {
+    for(MConfig config : configs) {
+      displayConfig(config, bundle);
+    }
+  }
+
+  /**
+   * Method prints the warning message of ACCEPTABLE status
+   * @param entity - link or job instance
+   */
+  public static void displayConfigWarning(MAccountableEntity entity) {
+    List<MConfig> configList = new ArrayList<MConfig>();
+    boolean showMessage = true;
+    if (entity instanceof MLink) {
+      MLink link = (MLink) entity;
+      configList.addAll(link.getConnectorLinkConfig().getConfigs());
+    } else if(entity instanceof MJob) {
+      MJob job = (MJob) entity;
+      configList.addAll(job.getJobConfig(Direction.FROM).getConfigs());
+      configList.addAll(job.getDriverConfig().getConfigs());
+      configList.addAll(job.getJobConfig(Direction.TO).getConfigs());
+    }
+    for(MConfig config : configList) {
+      if(config.getValidationStatus() == Status.ACCEPTABLE) {
+        if(showMessage) {
+          print("\n@|yellow %s|@\n", resourceString(Constants.RES_CONFIG_DISPLAYER_FORM_WARNING));
+          showMessage = false;
+        }
+        for(Message message : config.getValidationMessages()) {
+          ConfigFiller.warningMessage(message.getMessage());
+        }
+      }
+    }
+  }
+
+  private static void displayConfig(MConfig config, ResourceBundle bundle) {
+    print("  ");
+    println(bundle.getString(config.getLabelKey()));
+
+    for (MInput<?> input : config.getInputs()) {
+      print("    ");
+      print(bundle.getString(input.getLabelKey()));
+      print(": ");
+      if(!input.isEmpty()) {
+        if (input.isSensitive()) {
+          print("(%s)", resourceString(Constants.RES_CONFIG_DISPLAYER_INPUT_SENSITIVE));
+        } else {
+          // Based on the input type, let's perconfig specific load
+          switch (input.getType()) {
+            case STRING:
+              displayInputString((MStringInput) input);
+              break;
+            case INTEGER:
+              displayInputInteger((MIntegerInput) input);
+              break;
+            case BOOLEAN:
+              displayInputBoolean((MBooleanInput) input);
+              break;
+            case MAP:
+              displayInputMap((MMapInput) input);
+              break;
+            case ENUM:
+              displayInputEnum((MEnumInput) input);
+              break;
+            default:
+              print("\n%s " + input.getType(), resourceString(Constants.RES_CONFIG_DISPLAYER_UNSUPPORTED_DATATYPE));
+              return;
+          }
+        }
+      }
+      println("");
+    }
+  }
+
+  /**
+   * Display content of String input.
+   *
+   * @param input String input
+   */
+  private static void displayInputString(MStringInput input) {
+    print(input.getValue());
+  }
+
+  /**
+   * Display content of Integer input.
+   *
+   * @param input Integer input
+   */
+  private static void displayInputInteger(MIntegerInput input) {
+    print(input.getValue());
+  }
+
+  /**
+   * Display content of Boolean input.
+   *
+   * @param input Boolean input
+   */
+  private static void displayInputBoolean(MBooleanInput input) {
+    print(input.getValue());
+  }
+
+  /**
+   * Display content of Map input
+   *
+   * @param input Map input
+   */
+  private static void displayInputMap(MMapInput input) {
+    for(Map.Entry<String, String> entry : input.getValue().entrySet()) {
+      println();
+      print("      ");
+      print(entry.getKey());
+      print(" = ");
+      print(entry.getValue());
+    }
+  }
+
+  /**
+   * Display content of Enum input
+   *
+   * @param input Enum input
+   */
+  private static void displayInputEnum(MEnumInput input) {
+    print(input.getValue());
+  }
+
+  private ConfigDisplayer() {
+    // Do not instantiate
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigFiller.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigFiller.java b/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigFiller.java
new file mode 100644
index 0000000..c61d33b
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigFiller.java
@@ -0,0 +1,911 @@
+/**
+ * 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.sqoop.shell.utils;
+
+import jline.ConsoleReader;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.lang.StringUtils;
+import org.apache.sqoop.common.Direction;
+import org.apache.sqoop.model.MBooleanInput;
+import org.apache.sqoop.model.MLink;
+import org.apache.sqoop.model.MEnumInput;
+import org.apache.sqoop.model.MConfig;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MIntegerInput;
+import org.apache.sqoop.model.MMapInput;
+import org.apache.sqoop.model.MJob;
+import org.apache.sqoop.model.MNamedElement;
+import org.apache.sqoop.model.MStringInput;
+import org.apache.sqoop.model.MValidatedElement;
+import org.apache.sqoop.validation.Message;
+import org.apache.sqoop.validation.Status;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ResourceBundle;
+
+import static org.apache.sqoop.shell.ShellEnvironment.*;
+
+/**
+ * Convenient methods for retrieving user input and CLI options.
+ */
+public final class ConfigFiller {
+
+  /**
+   * Internal input that will be reused for loading names for link and
+   * job objects.
+   */
+  private static MStringInput nameInput = new MStringInput("object-name", false, (short)25);
+
+  /**
+   * Fill job object based on CLI options.
+   *
+   * @param line Associated console reader object
+   * @param job Job that user is suppose to fill in
+   * @return True if we filled all inputs, false if user has stopped processing
+   * @throws IOException
+   */
+  public static boolean fillJob(CommandLine line,
+                                MJob job)
+                                throws IOException {
+
+    job.setName(line.getOptionValue("name"));
+    return fillJobConfig(line,
+                     job.getJobConfig(Direction.FROM).getConfigs(),
+                     job.getJobConfig(Direction.TO).getConfigs(),
+                     job.getDriverConfig().getConfigs());
+  }
+
+  /**
+   * Fill link object based on CLI options.
+   *
+   * @param line Associated command line options
+   * @param link Link that user is suppose to fill in
+   * @return True if we filled all inputs, false if user has stopped processing
+   * @throws IOException
+   */
+  public static boolean fillLink(CommandLine line, MLink link) throws IOException {
+
+    link.setName(line.getOptionValue("name"));
+    return fillLinkConfig(line, link.getConnectorLinkConfig().getConfigs());
+  }
+
+  /**
+   * Load CLI options for link configs
+   *
+   * @param line CLI options container
+   * @param linkConfig from config to read or edit
+   * @return
+   * @throws IOException
+   */
+  public static boolean fillLinkConfig(CommandLine line,
+                                  List<MConfig> linkConfig)
+                                      throws IOException {
+    return fillConfigs("link", linkConfig, line);
+  }
+
+  /**
+   * Load CLI options for job configs
+   *
+   * @param line CLI options container
+   * @param fromConfig from config to read or edit
+   * @param toConfig to config to read or edit
+   * @param driverConfig driver config to read or edit
+   * @return
+   * @throws IOException
+   */
+  public static boolean fillJobConfig(CommandLine line,
+                                  List<MConfig> fromConfig,
+                                  List<MConfig> toConfig,
+                                  List<MConfig> driverConfig)
+                                      throws IOException {
+    return fillConfigs("from", fromConfig, line)
+        && fillConfigs("to", toConfig, line)
+        && fillConfigs("driver", driverConfig, line);
+  }
+
+  /**
+   * Load all CLI options for a list of configs.
+   *
+   * @param prefix placed at the beginning of the CLI option key
+   * @param configs Forms to read or edit
+   * @param line CLI options container
+   * @return
+   * @throws IOException
+   */
+  static boolean fillConfigs(String prefix, List<MConfig> configs, CommandLine line)
+      throws IOException {
+    for (MConfig config : configs) {
+      if (!fillConfig(prefix, config, line)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Load all CLI options for a particular config.
+   *
+   * @param prefix placed at the beginning of the CLI option key
+   * @param config Config to read or edit
+   * @param line CLI options container
+   * @return
+   * @throws IOException
+   */
+  @SuppressWarnings("rawtypes")
+  static boolean fillConfig(String prefix, MConfig config, CommandLine line) throws IOException {
+    for (MInput input : config.getInputs()) {
+      if (!fillInput(prefix, input, line)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Load CLI option.
+   * Chooses the appropriate 'fill' method to use based on input type.
+   *
+   * Keys for CLI options are automatically created from the 'prefix' argument
+   * and 'input' argument: <prefix>-<config name>-<input name>
+   *
+   * @param prefix placed at the beginning of the CLI option key
+   * @param input Input that we should read or edit
+   * @param line CLI options container
+   * @return
+   * @throws IOException
+   */
+  @SuppressWarnings("rawtypes")
+  public static boolean fillInput(String prefix, MInput input, CommandLine line) throws IOException {
+    // Based on the input type, let's perconfig specific load
+    switch (input.getType()) {
+    case STRING:
+      return fillInputString(prefix, (MStringInput) input, line);
+    case INTEGER:
+      return fillInputInteger(prefix, (MIntegerInput) input, line);
+    case BOOLEAN:
+      return fillInputBoolean(prefix, (MBooleanInput) input, line);
+    case MAP:
+      return fillInputMap(prefix, (MMapInput) input, line);
+    case ENUM:
+      return fillInputEnum(prefix, (MEnumInput) input, line);
+    default:
+      println("Unsupported data type " + input.getType());
+      return true;
+    }
+  }
+
+  /**
+   * Load CLI option for enum type.
+   *
+   * Currently only supports numeric values.
+   *
+   * @param prefix placed at the beginning of the CLI option key
+   * @param input Input that we should read or edit
+   * @param line CLI options container
+   * @return
+   * @throws IOException
+   */
+  private static boolean fillInputEnum(String prefix,
+                                       MEnumInput input,
+                                       CommandLine line)
+                                       throws IOException {
+    String opt = ConfigOptions.getOptionKey(prefix, input);
+    if (line.hasOption(opt)) {
+      String value = line.getOptionValue(opt);
+      int index = java.util.Arrays.asList(input.getValues()).indexOf(value);
+
+      if(index < 0) {
+        errorMessage(input, String.format("Invalid option %s. Please use one of %s.", value, StringUtils.join(input.getValues(), ", ")));
+        return false;
+      }
+
+      input.setValue(value);
+    } else {
+      input.setEmpty();
+    }
+    return true;
+  }
+
+  /**
+   * Load CLI options for map type.
+   *
+   * Parses Key-Value pairs that take the config "<key>=<value>&<key>=<value>&...".
+   *
+   * @param prefix placed at the beginning of the CLI option key
+   * @param input Input that we should read or edit
+   * @param line CLI options container
+   * @return
+   * @throws IOException
+   */
+  private static boolean fillInputMap(String prefix,
+                                      MMapInput input,
+                                      CommandLine line)
+                                      throws IOException {
+    String opt = ConfigOptions.getOptionKey(prefix, input);
+    if (line.hasOption(opt)) {
+      String value = line.getOptionValue(opt);
+      Map<String, String> values = new HashMap<String, String>();
+      String[] entries = value.split("&");
+      for (String entry : entries) {
+        if (entry.contains("=")) {
+          String[] keyValue = entry.split("=");
+          values.put(keyValue[0], keyValue[1]);
+        } else {
+          errorMessage(input, "Don't know what to do with " + entry);
+          return false;
+        }
+      }
+      input.setValue(values);
+    } else {
+      input.setEmpty();
+    }
+    return true;
+  }
+
+  /**
+   * Load integer input from CLI option.
+   *
+   * @param prefix placed at the beginning of the CLI option key
+   * @param input Input that we should read or edit
+   * @param line CLI options container
+   * @return
+   * @throws IOException
+   */
+  private static boolean fillInputInteger(String prefix,
+                                          MIntegerInput input,
+                                          CommandLine line)
+                                          throws IOException {
+    String opt = ConfigOptions.getOptionKey(prefix, input);
+    if (line.hasOption(opt)) {
+      try {
+        input.setValue(Integer.valueOf(line.getOptionValue(ConfigOptions.getOptionKey(prefix, input))));
+      } catch (NumberFormatException ex) {
+        errorMessage(input, "Input is not valid integer number");
+        return false;
+      }
+    } else {
+      input.setEmpty();
+    }
+    return true;
+  }
+
+  /**
+   * Load string input from CLI option.
+   *
+   * @param prefix placed at the beginning of the CLI option key
+   * @param input Input that we should read or edit
+   * @param line CLI options container
+   * @return
+   * @throws IOException
+   */
+  public static boolean fillInputString(String prefix,
+                                        MStringInput input,
+                                        CommandLine line)
+                                        throws IOException {
+    String opt = ConfigOptions.getOptionKey(prefix, input);
+    if (line.hasOption(opt)) {
+      String value = line.getOptionValue(ConfigOptions.getOptionKey(prefix, input));
+      if(value.length() > input.getMaxLength()) {
+        errorMessage(input, "Size of input exceeds allowance for this input"
+          + " field. Maximal allowed size is " + input.getMaxLength());
+      }
+      input.setValue(value);
+    } else {
+      input.setEmpty();
+    }
+    return true;
+  }
+
+  /**
+   * Load boolean input from CLI option.
+   *
+   * @param prefix placed at the beginning of the CLI option key
+   * @param input Input that we should read or edit
+   * @param line CLI options container
+   * @return
+   * @throws IOException
+   */
+  public static boolean fillInputBoolean(String prefix,
+                                         MBooleanInput input,
+                                         CommandLine line)
+                                         throws IOException {
+    String opt = ConfigOptions.getOptionKey(prefix, input);
+    if (line.hasOption(opt)) {
+      input.setValue(Boolean.valueOf(line.getOptionValue(ConfigOptions.getOptionKey(prefix, input))));
+    } else {
+      input.setEmpty();
+    }
+    return true;
+  }
+
+  /**
+   * Fill link object based on user input.
+   *
+   * @param reader Associated console reader object
+   * @param link Link that user is suppose to fill in
+   * @param linkConfigBundle Connector resource bundle
+   * @return True if we filled all inputs, false if user has stopped processing
+   * @throws IOException
+   */
+  public static boolean fillLinkWithBundle(ConsoleReader reader, MLink link, ResourceBundle linkConfigBundle)
+      throws IOException {
+
+    link.setName(getName(reader, link.getName()));
+    return fillLinkConfigWithBundle(reader, link.getConnectorLinkConfig().getConfigs(), linkConfigBundle);
+  }
+
+  /**
+   * Fill job object based on user input.
+   *
+   * @param reader Associated console reader object
+   * @param job Job that user is suppose to fill in
+   * @param fromConfigBundle Connector resource bundle
+   * @param driverConfigBundle Driver config resource bundle
+   * @return True if we filled all inputs, false if user has stopped processing
+   * @throws IOException
+   */
+  public static boolean fillJobWithBundle(ConsoleReader reader,
+                                MJob job,
+                                ResourceBundle fromConfigBundle,
+                                ResourceBundle toConfigBundle,
+                                ResourceBundle driverConfigBundle)
+                                throws IOException {
+
+    job.setName(getName(reader, job.getName()));
+
+    return fillJobConfigWithBundle(reader,
+                     job.getJobConfig(Direction.FROM).getConfigs(),
+                     fromConfigBundle,
+                     job.getJobConfig(Direction.TO).getConfigs(),
+                     toConfigBundle,
+                     job.getDriverConfig().getConfigs(),
+                     driverConfigBundle);
+  }
+  public static boolean fillLinkConfigWithBundle(ConsoleReader reader,
+                                  List<MConfig> linkConfig,
+                                  ResourceBundle linkConfigBundle) throws IOException {
+
+
+    if(!fillConfigsWithBundle(linkConfig, reader, linkConfigBundle)) {
+      return false;
+    }
+    return true;
+  }
+
+  public static boolean fillJobConfigWithBundle(ConsoleReader reader,
+                                  List<MConfig> fromConfig,
+                                  ResourceBundle fromConfigBundle,
+                                  List<MConfig> toConfig,
+                                  ResourceBundle toConfigBundle,
+                                  List<MConfig> driverConfig,
+                                  ResourceBundle driverConfigBundle) throws IOException {
+
+
+    // Job From config
+    if(!fillConfigsWithBundle(fromConfig, reader, fromConfigBundle)) {
+      return false;
+    }
+    // Job To config
+    if(!fillConfigsWithBundle(toConfig, reader, toConfigBundle)) {
+      return false;
+    }
+    // Job Driver config
+    if(!fillConfigsWithBundle(driverConfig, reader, driverConfigBundle)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public static boolean fillConfigsWithBundle(List<MConfig> configs, ConsoleReader reader,
+      ResourceBundle configBundle) throws IOException {
+    for (MConfig config : configs) {
+      if (!fillConfigWithBundle(config, reader, configBundle)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  @SuppressWarnings("rawtypes")
+  public static boolean fillConfigWithBundle(MConfig config, ConsoleReader reader, ResourceBundle bundle)
+      throws IOException {
+    println("");
+    println(bundle.getString(config.getLabelKey()));
+
+    // Print out config validation
+    printValidationMessage(config, false);
+    println("");
+
+    for (MInput input : config.getInputs()) {
+      if(!fillInputWithBundle(input, reader, bundle)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  @SuppressWarnings("rawtypes")
+  static boolean fillInputWithBundle(MInput input, ConsoleReader reader, ResourceBundle bundle)
+      throws IOException {
+    // Print out validation
+    printValidationMessage(input, false);
+
+    // Based on the input type, let's perconfig specific load
+    switch (input.getType()) {
+      case STRING:
+        return fillInputStringWithBundle((MStringInput) input, reader, bundle);
+      case INTEGER:
+        return fillInputInteger((MIntegerInput) input, reader, bundle);
+      case BOOLEAN:
+        return fillInputBooleanWithBundle((MBooleanInput) input, reader, bundle);
+      case MAP:
+        return fillInputMapWithBundle((MMapInput) input, reader, bundle);
+      case ENUM:
+        return fillInputEnumWithBundle((MEnumInput) input, reader, bundle);
+      default:
+        println("Unsupported data type " + input.getType());
+        return true;
+    }
+  }
+
+  /**
+   * Load user input for enum type.
+   *
+   * Print out numbered list of all available options and let user choose one
+   * item from that.
+   *
+   * @param input Input that we should read or edit
+   * @param reader Associated console reader
+   * @param bundle Resource bundle
+   * @return True if user with to continue with loading addtional inputs
+   * @throws IOException
+   */
+  private static boolean fillInputEnumWithBundle(MEnumInput input,
+                                       ConsoleReader reader,
+                                       ResourceBundle bundle)
+                                       throws IOException {
+    // Prompt in enum case
+    println(bundle.getString(input.getLabelKey()) + ": ");
+
+    // Indexes
+    int i = -1;
+    int lastChoice = -1;
+
+    // Print out all values as a numbered list
+    for(String value : input.getValues()) {
+      i++;
+
+      println("  " + i  + " : " + value);
+
+      // Only show last choice if not sensitive
+      if(!input.isEmpty() && value.equals(input.getValue()) && !input.isSensitive()) {
+        lastChoice = i;
+      }
+    }
+
+    // Prompt
+    reader.printString("Choose: ");
+
+    // Fill previously filled index when available
+    if(lastChoice != -1) {
+      reader.putString(Integer.toString(lastChoice));
+    }
+
+    reader.flushConsole();
+    String userTyped;
+    if(input.isSensitive()) {
+      userTyped = reader.readLine('*');
+    } else {
+      userTyped = reader.readLine();
+    }
+
+    if (userTyped == null) {
+      return false;
+    } else if (userTyped.isEmpty()) {
+      input.setEmpty();
+    } else {
+      Integer index;
+      try {
+        index = Integer.valueOf(userTyped);
+
+        if(index < 0 || index >= input.getValues().length) {
+          errorMessage("Invalid index");
+          return fillInputEnumWithBundle(input, reader, bundle);
+        }
+
+        input.setValue(input.getValues()[index]);
+      } catch (NumberFormatException ex) {
+        errorMessage("Input is not valid integer number");
+        return fillInputEnumWithBundle(input, reader, bundle);
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Load user input for map type.
+   *
+   * This implementation will load one map entry at the time. Current flows is
+   * as follows: if user did not enter anything (empty input) finish loading
+   * and return from function. If user specified input with equal sign (=),
+   * lets add new key value pair. Otherwise consider entire input as a key name
+   * and try to remove it from the map.
+   *
+   * Please note that following code do not supports equal sign in property
+   * name. It's however perfectly fine to have equal sign in value.
+   *
+   * @param input Input that we should read or edit
+   * @param reader Associated console reader
+   * @param bundle Resource bundle
+   * @return True if user wish to continue with loading additional inputs
+   * @throws IOException
+   */
+  private static boolean fillInputMapWithBundle(MMapInput input,
+                                      ConsoleReader reader,
+                                      ResourceBundle bundle)
+                                      throws IOException {
+    // Special prompt in Map case
+    println(bundle.getString(input.getLabelKey()) + ": ");
+
+    // Internal loading map
+    Map<String, String> values = input.getValue();
+    if(values == null) {
+      values = new HashMap<String, String>();
+    }
+
+    String userTyped;
+
+    while(true) {
+      // Print all current items in each iteration
+      // However do not printout if this input contains sensitive information.
+      println("There are currently " + values.size() + " values in the map:");
+      if (!input.isSensitive()) {
+        for(Map.Entry<String, String> entry : values.entrySet()) {
+          println(entry.getKey() + " = " + entry.getValue());
+        }
+      }
+
+      // Special prompt for Map entry
+      reader.printString("entry# ");
+      reader.flushConsole();
+
+      if(input.isSensitive()) {
+        userTyped = reader.readLine('*');
+      } else {
+        userTyped = reader.readLine();
+      }
+
+      if(userTyped == null) {
+        // Finish loading and return back to Sqoop shell
+        return false;
+      } else if(userTyped.isEmpty()) {
+        // User has finished loading data to Map input, either set input empty
+        // if there are no entries or propagate entries to the input
+        if(values.size() == 0) {
+          input.setEmpty();
+        } else {
+          input.setValue(values);
+        }
+        return true;
+      } else {
+        // User has specified regular input, let's check if it contains equals
+        // sign. Save new entry (or update existing one) if it does. Otherwise
+        // try to remove entry that user specified.
+        if(userTyped.contains("=")) {
+          String []keyValue = userTyped.split("=", 2);
+          values.put(handleUserInput(keyValue[0]), handleUserInput(keyValue[1]));
+        } else {
+          String key = handleUserInput(userTyped);
+          if(values.containsKey(key)) {
+            values.remove(key);
+          } else {
+            errorMessage("Don't know what to do with " + userTyped);
+          }
+        }
+      }
+
+    }
+  }
+
+  /**
+   * Handle special cases in user input.
+   *
+   * Preserve null and empty values, remove whitespace characters before and
+   * after loaded string and de-quote the string if it's quoted (to preserve
+   * spaces for example).
+   *
+   * @param input String loaded from user
+   * @return Unquoted transconfiged string
+   */
+  private static String handleUserInput(String input) {
+    // Preserve null and empty values
+    if(input == null) {
+      return null;
+    }
+    if(input.isEmpty()) {
+      return input;
+    }
+
+    // Removes empty characters at the begging and end of loaded string
+    input = input.trim();
+
+    int lastIndex = input.length() - 1;
+    char first = input.charAt(0);
+    char last = input.charAt(lastIndex);
+
+    // Remove quoting if present
+    if(first == '\'' && last == '\'') {
+      input = input.substring(1, lastIndex);
+    } else if(first == '"' && last == '"') {
+      input =  input.substring(1, lastIndex);
+    }
+
+    // Return final string
+    return input;
+  }
+
+  private static boolean fillInputInteger(MIntegerInput input,
+                                          ConsoleReader reader,
+                                          ResourceBundle bundle)
+                                          throws IOException {
+    generatePrompt(reader, bundle, input);
+
+    // Fill already filled data when available
+    // However do not printout if this input contains sensitive information.
+    if(!input.isEmpty() && !input.isSensitive()) {
+      reader.putString(input.getValue().toString());
+    }
+
+    // Get the data
+    String userTyped;
+    if(input.isSensitive()) {
+      userTyped = reader.readLine('*');
+    } else {
+      userTyped = reader.readLine();
+    }
+
+    if (userTyped == null) {
+      return false;
+    } else if (userTyped.isEmpty()) {
+      input.setEmpty();
+    } else {
+      Integer value;
+      try {
+        value = Integer.valueOf(userTyped);
+        input.setValue(value);
+      } catch (NumberFormatException ex) {
+        errorMessage("Input is not valid integer number");
+        return fillInputInteger(input, reader, bundle);
+      }
+
+      input.setValue(Integer.valueOf(userTyped));
+    }
+
+    return true;
+  }
+
+  /**
+   * Load string input from the user.
+   *
+   * @param input Input that we should load in
+   * @param reader Associated console reader
+   * @param bundle Resource bundle for this input
+   * @return
+   * @throws IOException
+   */
+  static boolean fillInputStringWithBundle(MStringInput input,
+                                        ConsoleReader reader,
+                                        ResourceBundle bundle)
+                                        throws IOException {
+    generatePrompt(reader, bundle, input);
+
+    // Fill already filled data when available
+    // However do not printout if this input contains sensitive information.
+    if(!input.isEmpty() && !input.isSensitive()) {
+      reader.putString(input.getValue());
+    }
+
+    // Get the data
+    String userTyped;
+    if(input.isSensitive()) {
+       userTyped = reader.readLine('*');
+    } else {
+      userTyped = reader.readLine();
+    }
+
+    if (userTyped == null) {
+      // Propagate end of loading process
+      return false;
+    } else if (userTyped.isEmpty()) {
+      // Empty input in case that nothing was given
+      input.setEmpty();
+    } else {
+      // Set value that user has entered
+      input.setValue(userTyped);
+
+      // Check that it did not exceeds maximal allowance for given input
+      if(userTyped.length() > input.getMaxLength()) {
+        errorMessage("Size of input exceeds allowance for this input"
+          + " field. Maximal allowed size is " + input.getMaxLength());
+        return fillInputStringWithBundle(input, reader, bundle);
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Load boolean input from the user.
+   *
+   * @param input Input that we should load in
+   * @param reader Associated console reader
+   * @param bundle Resource bundle for this input
+   * @return
+   * @throws IOException
+   */
+  static boolean fillInputBooleanWithBundle(MBooleanInput input,
+                                         ConsoleReader reader,
+                                         ResourceBundle bundle)
+                                         throws IOException {
+    generatePrompt(reader, bundle, input);
+
+    // Fill already filled data when available
+    // However do not printout if this input contains sensitive information.
+    if(!input.isEmpty() && !input.isSensitive()) {
+      reader.putString(input.getValue().toString());
+    }
+
+    // Get the data
+    String userTyped;
+    if(input.isSensitive()) {
+       userTyped = reader.readLine('*');
+    } else {
+      userTyped = reader.readLine();
+    }
+
+    if (userTyped == null) {
+      // Propagate end of loading process
+      return false;
+    } else if (userTyped.isEmpty()) {
+      // Empty input in case that nothing was given
+      input.setEmpty();
+    } else {
+      // Set value that user has entered
+      input.setValue(Boolean.valueOf(userTyped));
+    }
+
+    return true;
+  }
+
+  @SuppressWarnings("rawtypes")
+  static void generatePrompt(ConsoleReader reader, ResourceBundle bundle, MInput input)
+      throws IOException {
+    reader.printString(bundle.getString(input.getLabelKey()) + ": ");
+    reader.flushConsole();
+  }
+
+  static String getName(ConsoleReader reader, String name) throws IOException {
+    if (name == null) {
+      nameInput.setEmpty();
+    } else {
+      nameInput.setValue(name);
+    }
+
+    fillInputStringWithBundle(nameInput, reader, getResourceBundle());
+
+    return nameInput.getValue();
+  }
+
+  /**
+   * Print validation message in cases that it's not in state "FINE"
+   *
+   * @param element Validated element
+   */
+  static void printValidationMessage(MValidatedElement element, boolean includeInputPrefix) {
+    if(element.getValidationStatus() == Status.getDefault()) {
+      return;
+    }
+
+    for(Message message : element.getValidationMessages())
+    switch (message.getStatus()) {
+      case UNACCEPTABLE:
+        if (includeInputPrefix) {
+          errorMessage(element, message.getMessage());
+        } else {
+          errorMessage(message.getMessage());
+        }
+        break;
+      case ACCEPTABLE:
+        if (includeInputPrefix) {
+          warningMessage(element, message.getMessage());
+        } else {
+          warningMessage(message.getMessage());
+        }
+        break;
+      default:
+        // Simply ignore all other states for the moment
+        break;
+    }
+  }
+
+  static void errorMessage(String message) {
+    println("Error message: @|red " + message + " |@");
+  }
+
+  static void errorMessage(MNamedElement input, String message) {
+    print(input.getName());
+    print(": ");
+    errorMessage(message);
+  }
+
+  static void warningMessage(String message) {
+    println("Warning message: @|yellow " + message + " |@");
+  }
+
+  static void warningMessage(MNamedElement input, String message) {
+    print(input.getName());
+    print(": ");
+    warningMessage(message);
+  }
+
+  public static void errorIntroduction() {
+    println("\n @|red There are issues with entered data, please revise your input:|@");
+  }
+
+  // link object has the connector link config
+  public static void printLinkValidationMessages(MLink link) {
+    for (MConfig config : link.getConnectorLinkConfig().getConfigs()) {
+      for (MInput<?> input : config.getInputs()) {
+        printValidationMessage(input, true);
+      }
+    }
+  }
+
+  // job has the from/to and the driver config
+  public static void printJobValidationMessages(MJob job) {
+    for (MConfig config : job.getJobConfig(Direction.FROM).getConfigs()) {
+      for (MInput<?> input : config.getInputs()) {
+        printValidationMessage(input, true);
+      }
+    }
+
+    for (MConfig config : job.getJobConfig(Direction.TO).getConfigs()) {
+      for (MInput<?> input : config.getInputs()) {
+        printValidationMessage(input, true);
+      }
+    }
+
+    for (MConfig config : job.getDriverConfig().getConfigs()) {
+      for (MInput<?> input : config.getInputs()) {
+        printValidationMessage(input, true);
+      }
+    }
+  }
+
+  private ConfigFiller() {
+    // Do not instantiate
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigOptions.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigOptions.java b/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigOptions.java
new file mode 100644
index 0000000..97b6e3b
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/utils/ConfigOptions.java
@@ -0,0 +1,117 @@
+/**
+ * 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.sqoop.shell.utils;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.sqoop.common.SqoopException;
+import org.apache.sqoop.model.MConfig;
+import org.apache.sqoop.model.MInput;
+import org.apache.sqoop.model.MInputType;
+import org.apache.sqoop.shell.core.ShellError;
+
+/**
+ * Utilities for automatically creating org.apache.commons.cli.Option objects.
+ */
+public class ConfigOptions {
+  /**
+   * This method is used to automatically generate keys
+   * for a particular input.
+   *
+   * @param prefix Prefix to prepend to CLI option keys
+   * @param input
+   * @return
+   */
+  @SuppressWarnings("rawtypes")
+  public static String getOptionKey(String prefix, MInput input) {
+    return prefix + "-" + input.getName().replace('.', '-');
+  }
+
+  /**
+   * This method is used to automatically generate CLI options
+   * for a list of configs.
+   *
+   * @param prefix Prefix to prepend to CLI option keys
+   * @param configs Forms to get options for
+   * @return
+   */
+  public static List<Option> getConfigsOptions(String prefix, List<MConfig> configs) {
+    List<Option> options = new LinkedList<Option>();
+    for (MConfig config : configs) {
+      List<Option> configOptions = getConfigOptions(prefix, config);
+      options.addAll(configOptions);
+    }
+    return options;
+  }
+
+  /**
+   * This method is used to automatically generate CLI options
+   * for a particular config.
+   *
+   * @param prefix Prefix to prepend to CLI option keys
+   * @param config Config to get options for
+   * @return List<Option>
+   */
+  @SuppressWarnings({ "rawtypes", "static-access" })
+  public static List<Option> getConfigOptions(String prefix, MConfig config) {
+    List<Option> options = new LinkedList<Option>();
+    for (MInput input : config.getInputs()) {
+      if (input.getType().equals(MInputType.BOOLEAN)) {
+        options.add(OptionBuilder
+                    .withLongOpt(getOptionKey(prefix, input))
+                    .create());
+      } else {
+        options.add(OptionBuilder
+                    .withLongOpt(getOptionKey(prefix, input))
+                    .hasArg()
+                    .create());
+      }
+    }
+    return options;
+  }
+
+  /**
+   * Parses command line options.
+   *
+   * @param options parse arglist against these.
+   * @param start beginning index in arglist.
+   * @param arglist arguments to parse.
+   * @param stopAtNonOption stop parsing when nonoption found in arglist.
+   * @return CommandLine object
+   */
+  public static CommandLine parseOptions(Options options, int start, List<String> arglist, boolean stopAtNonOption) {
+    String[] args = arglist.subList(start, arglist.size()).toArray(new String[arglist.size() - start]);
+
+    CommandLineParser parser = new GnuParser();
+    CommandLine line;
+    try {
+      line = parser.parse(options, args, stopAtNonOption);
+    } catch (ParseException e) {
+      throw new SqoopException(ShellError.SHELL_0003, e.getMessage(), e);
+    }
+    return line;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/shell/src/main/java/org/apache/sqoop/shell/utils/DynamicConfigOptions.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/DynamicConfigOptions.java b/shell/src/main/java/org/apache/sqoop/shell/utils/DynamicConfigOptions.java
new file mode 100644
index 0000000..d12bd2f
--- /dev/null
+++ b/shell/src/main/java/org/apache/sqoop/shell/utils/DynamicConfigOptions.java
@@ -0,0 +1,35 @@
+/**
+ * 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.sqoop.shell.utils;
+
+import org.apache.commons.cli.Options;
+
+/**
+ * Automatically create options for different components.
+ */
+@SuppressWarnings("serial")
+public abstract class DynamicConfigOptions<M> extends Options {
+
+  /**
+   * Create dynamic options.
+   *
+   * @param model generate options from this
+   * @return this
+   */
+  public abstract void prepareOptions(M model);
+}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/shell/src/main/java/org/apache/sqoop/shell/utils/DynamicFormOptions.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/DynamicFormOptions.java b/shell/src/main/java/org/apache/sqoop/shell/utils/DynamicFormOptions.java
deleted file mode 100644
index cc63610..0000000
--- a/shell/src/main/java/org/apache/sqoop/shell/utils/DynamicFormOptions.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * 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.sqoop.shell.utils;
-
-import org.apache.commons.cli.Options;
-
-/**
- * Automatically create options for different components.
- */
-@SuppressWarnings("serial")
-public abstract class DynamicFormOptions<M> extends Options {
-
-  /**
-   * Create dynamic options.
-   *
-   * @param model generate options from this
-   * @return this
-   */
-  public abstract void prepareOptions(M model);
-}

http://git-wip-us.apache.org/repos/asf/sqoop/blob/f63c080d/shell/src/main/java/org/apache/sqoop/shell/utils/FormDisplayer.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/sqoop/shell/utils/FormDisplayer.java b/shell/src/main/java/org/apache/sqoop/shell/utils/FormDisplayer.java
deleted file mode 100644
index dcbccef..0000000
--- a/shell/src/main/java/org/apache/sqoop/shell/utils/FormDisplayer.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/**
- * 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.sqoop.shell.utils;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.sqoop.common.Direction;
-import org.apache.sqoop.model.MAccountableEntity;
-import org.apache.sqoop.model.MBooleanInput;
-import org.apache.sqoop.model.MLink;
-import org.apache.sqoop.model.MConnector;
-import org.apache.sqoop.model.MEnumInput;
-import org.apache.sqoop.model.MForm;
-import org.apache.sqoop.model.MDriverConfig;
-import org.apache.sqoop.model.MInput;
-import org.apache.sqoop.model.MInputType;
-import org.apache.sqoop.model.MIntegerInput;
-import org.apache.sqoop.model.MJob;
-import org.apache.sqoop.model.MMapInput;
-import org.apache.sqoop.model.MStringInput;
-import org.apache.sqoop.shell.core.Constants;
-import org.apache.sqoop.validation.Message;
-import org.apache.sqoop.validation.Status;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.ResourceBundle;
-
-import static org.apache.sqoop.shell.ShellEnvironment.*;
-
-/**
- * Convenience static methods for displaying form related information
- */
-public final class FormDisplayer {
-
-  public static void displayFormMetadataDetails(MDriverConfig driverConfig,
-                                                ResourceBundle bundle) {
-    displayFormsMetadata(
-      driverConfig.getConnectionForms().getForms(),
-      resourceString(Constants.RES_FORMDISPLAYER_CONNECTION),
-      bundle);
-
-    displayFormsMetadata(
-      driverConfig.getJobForms().getForms(),
-      resourceString(Constants.RES_FORMDISPLAYER_JOB),
-      bundle);
-  }
-
-  public static void displayFormMetadataDetails(MConnector connector,
-                                                ResourceBundle bundle) {
-    displayFormsMetadata(
-        connector.getConnectionForms().getForms(),
-        resourceString(Constants.RES_FORMDISPLAYER_CONNECTION),
-        bundle);
-
-    // @TODO(Abe): Validate From/To output is correct.
-    displayFormsMetadata(
-        connector.getJobForms(Direction.FROM).getForms(),
-        Direction.FROM.toString() + " " + resourceString(Constants.RES_FORMDISPLAYER_JOB),
-        bundle);
-
-    displayFormsMetadata(
-        connector.getJobForms(Direction.TO).getForms(),
-        Direction.TO.toString() + " " + resourceString(Constants.RES_FORMDISPLAYER_JOB),
-        bundle);
-  }
-
-  public static void displayFormsMetadata(List<MForm> forms,
-                                         String type,
-                                         ResourceBundle bundle) {
-    Iterator<MForm> fiter = forms.iterator();
-    int findx = 1;
-    while (fiter.hasNext()) {
-      print("    ");
-      print(type);
-      print(" %s ", resourceString(Constants.RES_FORMDISPLAYER_FORM));
-      print(findx++);
-      println(":");
-
-      MForm form = fiter.next();
-      print("      %s: ", resourceString(Constants.RES_FORMDISPLAYER_NAME));
-      println(form.getName());
-
-      // Label
-      print("      %s: ", resourceString(Constants.RES_FORMDISPLAYER_LABEL));
-      println(bundle.getString(form.getLabelKey()));
-
-      // Help text
-      print("      %s: ", resourceString(Constants.RES_FORMDISPLAYER_HELP));
-      println(bundle.getString(form.getHelpKey()));
-
-      List<MInput<?>> inputs = form.getInputs();
-      Iterator<MInput<?>> iiter = inputs.iterator();
-      int iindx = 1;
-      while (iiter.hasNext()) {
-        print("      %s ", resourceString(Constants.RES_FORMDISPLAYER_INPUT));
-        print(iindx++);
-        println(":");
-
-        MInput<?> input = iiter.next();
-        print("        %s: ", resourceString(Constants.RES_FORMDISPLAYER_NAME));
-        println(input.getName());
-        print("        %s: ", resourceString(Constants.RES_FORMDISPLAYER_LABEL));
-        println(bundle.getString(input.getLabelKey()));
-        print("        %s: ", resourceString(Constants.RES_FORMDISPLAYER_HELP));
-        println(bundle.getString(input.getHelpKey()));
-        print("        %s: ", resourceString(Constants.RES_FORMDISPLAYER_TYPE));
-        println(input.getType());
-        print("        %s: ", resourceString(Constants.RES_FORMDISPLAYER_SENSITIVE));
-        println(input.isSensitive());
-        if (input.getType() == MInputType.STRING) {
-          print("        %s: ", resourceString(Constants.RES_FORMDISPLAYER_SIZE));
-          println(((MStringInput)input).getMaxLength());
-        } else if(input.getType() == MInputType.ENUM) {
-          print("        %s: ", resourceString(Constants.RES_FORMDISPLAYER_POSSIBLE_VALUES));
-          println(StringUtils.join(((MEnumInput)input).getValues(), ","));
-        }
-      }
-    }
-  }
-
-  public static void displayForms(List<MForm> forms, ResourceBundle bundle) {
-    for(MForm form : forms) {
-      displayForm(form, bundle);
-    }
-  }
-
-  /**
-   * Method prints the warning message of ACCEPTABLE status
-   * @param entity - link or job instance
-   */
-  public static void displayFormWarning(MAccountableEntity entity) {
-    List<MForm> formList = new ArrayList<MForm>();
-    boolean showMessage = true;
-    if (entity instanceof MLink) {
-      MLink link = (MLink) entity;
-      formList.addAll(link.getConnectorPart().getForms());
-      formList.addAll(link.getFrameworkPart().getForms());
-    } else if(entity instanceof MJob) {
-      MJob job = (MJob) entity;
-      formList.addAll(job.getConnectorPart(Direction.FROM).getForms());
-      formList.addAll(job.getFrameworkPart().getForms());
-      formList.addAll(job.getConnectorPart(Direction.TO).getForms());
-    }
-    for(MForm form : formList) {
-      if(form.getValidationStatus() == Status.ACCEPTABLE) {
-        if(showMessage) {
-          print("\n@|yellow %s|@\n", resourceString(Constants.RES_FORMDISPLAYER_FORM_WARNING));
-          showMessage = false;
-        }
-        for(Message message : form.getValidationMessages()) {
-          FormFiller.warningMessage(message.getMessage());
-        }
-      }
-    }
-  }
-
-  private static void displayForm(MForm form, ResourceBundle bundle) {
-    print("  ");
-    println(bundle.getString(form.getLabelKey()));
-
-    for (MInput<?> input : form.getInputs()) {
-      print("    ");
-      print(bundle.getString(input.getLabelKey()));
-      print(": ");
-      if(!input.isEmpty()) {
-        if (input.isSensitive()) {
-          print("(%s)", resourceString(Constants.RES_FORMDISPLAYER_INPUT_SENSITIVE));
-        } else {
-          // Based on the input type, let's perform specific load
-          switch (input.getType()) {
-            case STRING:
-              displayInputString((MStringInput) input);
-              break;
-            case INTEGER:
-              displayInputInteger((MIntegerInput) input);
-              break;
-            case BOOLEAN:
-              displayInputBoolean((MBooleanInput) input);
-              break;
-            case MAP:
-              displayInputMap((MMapInput) input);
-              break;
-            case ENUM:
-              displayInputEnum((MEnumInput) input);
-              break;
-            default:
-              print("\n%s " + input.getType(), resourceString(Constants.RES_FORMDISPLAYER_UNSUPPORTED_DATATYPE));
-              return;
-          }
-        }
-      }
-      println("");
-    }
-  }
-
-  /**
-   * Display content of String input.
-   *
-   * @param input String input
-   */
-  private static void displayInputString(MStringInput input) {
-    print(input.getValue());
-  }
-
-  /**
-   * Display content of Integer input.
-   *
-   * @param input Integer input
-   */
-  private static void displayInputInteger(MIntegerInput input) {
-    print(input.getValue());
-  }
-
-  /**
-   * Display content of Boolean input.
-   *
-   * @param input Boolean input
-   */
-  private static void displayInputBoolean(MBooleanInput input) {
-    print(input.getValue());
-  }
-
-  /**
-   * Display content of Map input
-   *
-   * @param input Map input
-   */
-  private static void displayInputMap(MMapInput input) {
-    for(Map.Entry<String, String> entry : input.getValue().entrySet()) {
-      println();
-      print("      ");
-      print(entry.getKey());
-      print(" = ");
-      print(entry.getValue());
-    }
-  }
-
-  /**
-   * Display content of Enum input
-   *
-   * @param input Enum input
-   */
-  private static void displayInputEnum(MEnumInput input) {
-    print(input.getValue());
-  }
-
-  private FormDisplayer() {
-    // Do not instantiate
-  }
-}