001    package org.hackystat.sensor.xmldata;
002    
003    import java.util.ArrayList;
004    import java.util.HashMap;
005    import java.util.List;
006    import java.util.Map;
007    import java.util.Map.Entry;
008    
009    import org.hackystat.sensor.xmldata.option.OptionFactory;
010    import org.hackystat.sensor.xmldata.option.OptionHandler;
011    import org.hackystat.sensor.xmldata.option.Options;
012    import org.hackystat.sensorshell.SensorShellProperties;
013    import org.hackystat.sensorshell.SensorShellException;
014    
015    /**
016     * The class which parses the command-line arguments specified by the user,
017     * validates the created options and their parameters, and executes the options.
018     * @author Austen Ito
019     * 
020     */
021    public class XmlDataController {
022      /** The class that manages the options created from the user's arguments. */
023      private OptionHandler optionHandler = null;
024      /** The class which encapsulates the firing of messages. */
025      private MessageDelegate messageDelegate = null;
026      /** The list of command-line arguments. */
027      private List<String> arguments = new ArrayList<String>();
028      /** True if all command-line arguments have been parsed correctly. */
029      private boolean hasParsed = true;
030      /**
031       * The mapping of options -> objects that are set during each option's
032       * processing.
033       */
034      private Map<Options, Object> optionMap = new HashMap<Options, Object>();
035    
036      /**
037       * Constructs this controller with the classes that help manage the
038       * command-line arguments and message capabilities.
039       */
040      public XmlDataController() {
041        this.optionHandler = new OptionHandler(this);
042        this.messageDelegate = new MessageDelegate(this);
043        this.optionMap.put(Options.UNIQUE_TSTAMP, Boolean.FALSE);
044        this.optionMap.put(Options.SET_RUNTIME, Boolean.FALSE);
045      }
046    
047      /**
048       * This method parses the specified command-line arguments and creates
049       * options, which can be validated and executed.
050       */
051      private void processArguments() {
052        Map<String, List<String>> optionToArgs = new HashMap<String, List<String>>();
053        String currentOption = "";
054    
055        // Iterate through all -option <arguments>... pairings to build a mapping of
056        // option -> arguments.
057        for (String argument : this.arguments) {
058          // If the current string is an option flag, create a new mapping.
059          if (this.optionHandler.isOption(argument)) {
060            if (optionToArgs.containsKey(argument)) {
061              this.fireMessage("The option, " + argument + ", may not have duplicates.");
062              this.hasParsed = false;
063              break;
064            }
065            optionToArgs.put(argument, new ArrayList<String>());
066            currentOption = argument;
067          }
068          // Else, add the argument to the option flag list.
069          else {
070            List<String> args = optionToArgs.get(currentOption);
071            if (args == null) {
072              this.fireMessage("The argument, " + argument + ", is not supported.");
073              this.hasParsed = false;
074              break;
075            }
076            args.add(argument);
077            optionToArgs.put(currentOption, args);
078          }
079        }
080    
081        // Next, let's create the options using the command-line information.
082        for (Entry<String, List<String>> entry : optionToArgs.entrySet()) {
083          String optionName = entry.getKey();
084          List<String> optionParams = entry.getValue();
085          this.optionHandler.addOption(OptionFactory.getInstance(this, optionName, optionParams));
086        }
087      }
088    
089      /**
090       * Adds a mapping of the specified option to the specified object. This allows
091       * options to use objects associated with other options during the option's
092       * execution phase.
093       * @param option the option that is associated with an object.
094       * @param object the object mapped to an option.
095       */
096      public void addOptionObject(Options option, Object object) {
097        this.optionMap.put(option, object);
098      }
099    
100      /**
101       * Returns the object mapped to the specified option. If no object exists,
102       * null is returned. It is up to the calling object to determine the type of
103       * object returned.
104       * @param option the option that is the key of the requested object.
105       * @return the object mapped to the specified option.
106       */
107      public Object getOptionObject(Options option) {
108        return this.optionMap.get(option);
109      }
110    
111      /**
112       * Processes the command-line arguments and creates the objects that can be
113       * executed.
114       * @param arguments the specified list of command-line arguments.
115       */
116      public void processArguments(List<String> arguments) {
117        this.arguments = arguments;
118        this.optionHandler.clearOptions();
119        this.processArguments();
120      }
121    
122      /** Executes all of the options specified by the user. */
123      public void execute() {
124        if (this.hasParsed && this.optionHandler.isOptionsValid()
125            && this.optionHandler.hasRequiredOptions()) {
126          this.optionHandler.processOptions();
127          this.optionHandler.execute();
128        }
129      }
130    
131      /**
132       * Displays the specified message. The same message is displayed even if the
133       * verbose option is enabled.
134       * @param message the specified message to display.
135       */
136      public void fireMessage(String message) {
137        this.messageDelegate.fireMessage(message);
138      }
139    
140      /**
141       * Displays the specified message if verbose mode is enabled.
142       * @param message the specified message to display.
143       */
144      public void fireVerboseMessage(String message) {
145        this.messageDelegate.fireVerboseMessage(message);
146      }
147    
148      /**
149       * Displays the specified message is verbose mode is disabled or the verbose
150       * message if verbose mode is enabled.
151       * @param message the specified message.
152       * @param verboseMessage the specified verbose message.
153       */
154      public void fireMessage(String message, String verboseMessage) {
155        this.messageDelegate.fireMessage(message, verboseMessage);
156      }
157    
158      /**
159       * Returns the SensorBase host stored in the sensor properties file.
160       * @return the SensorBase host string.
161       */
162      public String getHost() {
163        SensorShellProperties properties;
164        try {
165          properties = new SensorShellProperties();
166          return properties.getSensorBaseHost();
167        }
168        catch (SensorShellException e) {
169          String msg = "Problem creating SensorShellProperties: " + e.getMessage();
170          this.fireMessage(msg);
171        }
172        return "";
173      }
174    }