/**
   * Saves the mappings to the according preferences file.<br>
   * Mappings to <code>null</code> are not saved, so if you want to clear a mapping, use <code>null
   * </code> as value.<br>
   * Even if the saving process fails, the mappings are kept while the application is running.
   */
  protected void store() {
    Properties props = new Properties();
    try {
      FileInputStream fileInputStream = new FileInputStream(Constants.COMMAND_BINDINGS_FILE);
      props.load(fileInputStream);
      fileInputStream.close();
    } catch (FileNotFoundException e) {
      logClass.error(
          "Error: "
              + e.getMessage() // $NON-NLS-1$
              + Constants.LINE_SEPARATOR,
          e);
    } catch (IOException e) {
      logClass.error(
          "Error: "
              + e.getMessage() // $NON-NLS-1$
              + Constants.LINE_SEPARATOR,
          e);
    }

    List<Object> toRemove = new ArrayList<Object>();
    for (Object entry : props.keySet()) {
      if (entry.toString().startsWith(SAVE_KEY)) {
        toRemove.add(entry);
      }
    }
    for (Object obj : toRemove) {
      props.remove(obj);
    }

    for (Entry<String, K> entry : commandMapping.entrySet()) {
      if (entry.getValue() != null) {
        props.put(SAVE_KEY + entry.getKey(), saveObject(entry.getValue()));
      }
    }
    try {
      FileOutputStream fileOutputStream = new FileOutputStream(Constants.COMMAND_BINDINGS_FILE);
      props.store(fileOutputStream, "Mapping from commands to keys"); // $NON-NLS-1$
      fileOutputStream.close();
    } catch (FileNotFoundException e) {
      logClass.error(
          "Error: "
              + e.getMessage() // $NON-NLS-1$
              + Constants.LINE_SEPARATOR,
          e);
    } catch (IOException e) {
      logClass.error(
          "Error: "
              + e.getMessage() // $NON-NLS-1$
              + Constants.LINE_SEPARATOR,
          e);
    }
  }
  /**
   * Clears all mappings and (re-)loads the mappings from the according preferences file into the
   * local structure.
   */
  private void reload() {
    commandMapping.clear();
    identifierToCommand.clear();

    Properties props = new Properties();
    File f = new File(Constants.COMMAND_BINDINGS_FILE);
    if (f.exists()) {
      try {
        props.load(new FileInputStream(f));
        for (Entry<Object, Object> entry : props.entrySet()) {
          String pluginCommand = (String) entry.getKey();
          int underscoreIndex = pluginCommand.lastIndexOf("_"); // $NON-NLS-1$
          String mainClass = pluginCommand.substring(0, underscoreIndex);
          String commandKey = pluginCommand.substring(underscoreIndex + 1);

          if (pluginCommand.startsWith(SAVE_KEY)) {

            mainClass = mainClass.replaceFirst(SAVE_KEY, ""); // $NON-NLS-1$
            CommandDefinition def = CommandDefinition.getSimpleCommandDef(mainClass, commandKey);
            String value = (String) entry.getValue();
            K recoverObject = recoverObject(value);
            if (recoverObject != null) {
              addCommandMappingInternal(def, recoverObject);
            }
          }
        }
      } catch (FileNotFoundException e) {
        logClass.error(
            "Error: "
                + e.getMessage() // $NON-NLS-1$
                + Constants.LINE_SEPARATOR,
            e);
      } catch (IOException e) {
        logClass.error(
            "Error: "
                + e.getMessage() // $NON-NLS-1$
                + Constants.LINE_SEPARATOR,
            e);
      }
    }
  }
 /**
  * Gets the bind object for the given command
  *
  * @param command the plugin command to get the object for
  * @return the object or <code>null</code> if none found for the given plugin command
  */
 protected K getObjectInternal(CommandDefinition command) {
   K object = commandMapping.get(command.getIdentifierString());
   return object;
 }
 /**
  * Gets the plugin command for the given object
  *
  * @param object the object to get the command for
  * @return the plugin command for the given object or <code>null</code> if no mapping exists
  */
 protected CommandDefinition getCommandInternal(K object) {
   String key = commandMapping.getKey(object);
   return identifierToCommand.get(key);
 }
 /**
  * Binds the given object to the given command.<br>
  * Mappings to <code>null</code> are not save, so if you want to clear a mapping, use <code>null
  * </code> as value for the key sequence.<br>
  *
  * @param command the plugin command
  * @param object the object to bind to the command
  */
 protected void addCommandMappingInternal(CommandDefinition command, K object) {
   commandMapping.put(command.getIdentifierString(), object);
   identifierToCommand.put(command.getIdentifierString(), command);
 }