Index: feeds_ui/feeds_ui.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/feeds_ui/feeds_ui.admin.inc,v
retrieving revision 1.34
diff -u -r1.34 feeds_ui.admin.inc
--- feeds_ui/feeds_ui.admin.inc	10 Jul 2010 23:30:19 -0000	1.34
+++ feeds_ui/feeds_ui.admin.inc	20 Jul 2010 12:49:57 -0000
@@ -530,6 +530,7 @@
   );
 
   if (is_array($mappings)) {
+    $form['mappings']['#tree'] = TRUE;
     foreach ($mappings as $i => $mapping) {
 
       $mappings[$i]['source'] = isset($source_options) ? $source_options[$mappings[$i]['source']] : $mappings[$i]['source'];
@@ -553,6 +554,15 @@
         '#prefix' => '<div class="feeds-ui-checkbox-link">',
         '#suffix' => '</div>',
       );
+
+      // Declare the mappings data in the hidden field, so later
+      // the full mapping data will be submitted in $form_state['values']['mappings'].
+      foreach($mapping as $k => $v) {
+        $form['mappings'][$i][$k] = array (
+          '#type' => 'hidden',
+          '#value' => $v,
+        );
+      }
     }
   }
 
@@ -593,9 +603,23 @@
  * Submit handler for add button on feeds_ui_mapping_form().
  */
 function feeds_ui_mapping_form_add_submit($form, &$form_state) {
+  dpm($form_state['values']);
+
   $importer = $form['#importer'];
   try {
-    $importer->processor->addMapping($form_state['values']['source'], $form_state['values']['target']);
+    // addMapping method is now used for custom FeedsProcessor
+    // to declare what they want to do when mapping is added
+    // e.g. FeedsDataProcessor
+    if (method_exists($importer->processor, 'addMapping')) {
+      $importer->processor->addMapping($form_state['values']['source'], $form_state['values']['target']);
+    }
+
+    $form_state['values']['mappings'][] = array(
+      'source' => $form_state['values']['source'],
+      'target' => $form_state['values']['target'],
+      'unique' => FALSE,
+    );
+    $importer->processor->addConfig($form_state['values']);
     $importer->processor->save();
     drupal_set_message(t('Mapping has been added.'));
   }
@@ -614,16 +638,23 @@
   // step, that's fine.
   if (isset($form_state['values']['unique_flags'])) {
     foreach ($form_state['values']['unique_flags'] as $k => $v) {
-      $processor->setUnique($mappings[$k]['source'], $mappings[$k]['target'], $v);
+      $values['mappings'][$k]['unique'] = $v;
     }
   }
 
   foreach ($form_state['values']['remove_flags'] as $k => $v) {
     if ($v) {
-      $processor->removeMapping($mappings[$k]['source'], $mappings[$k]['target']);
+      unset($values['mappings'][$k]);
+      // Keep or keys clean.
+      $values['mappings'] = array_values($values['mappings']);
     }
   }
   drupal_set_message(t('Your changes have been saved.'));
+
+  // Because now full mapping is submitted, so no further validation for
+  // out of sync mappings is needed (i.e. the mapping is modified by other people while
+  // we are at it). Simply replace it.
+  $processor->addConfig($form_state['values']);
   $processor->save();
 }
 
Index: plugins/FeedsDataProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsDataProcessor.inc,v
retrieving revision 1.15
diff -u -r1.15 FeedsDataProcessor.inc
--- plugins/FeedsDataProcessor.inc	13 Jul 2010 19:32:06 -0000	1.15
+++ plugins/FeedsDataProcessor.inc	20 Jul 2010 12:22:53 -0000
@@ -136,9 +136,6 @@
         throw new Exception(t('Field !field_name already exists as a mapping target. Remove it from mapping if you would like to map another source to it. Remove it from !data_table table if you would like to change its definition.', array('!field_name' => $field_name, '!data_table' => l($this->table()->get('name'), 'admin/content/data'))));
       }
     }
-
-    // Let parent populate the mapping configuration.
-    parent::addMapping($source, $target, $unique);
   }
 
   /**
Index: plugins/FeedsProcessor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/feeds/plugins/FeedsProcessor.inc,v
retrieving revision 1.14
diff -u -r1.14 FeedsProcessor.inc
--- plugins/FeedsProcessor.inc	18 Jul 2010 18:33:43 -0000	1.14
+++ plugins/FeedsProcessor.inc	20 Jul 2010 12:23:18 -0000
@@ -159,54 +159,6 @@
   }
 
   /**
-   * Add a mapping to existing mappings.
-   *
-   * @param $source
-   *   A string that identifies a source element.
-   * @param $target
-   *   A string that identifies a target element.
-   * @param $unique
-   *   A boolean that defines whether the target value should be unique. If
-   *   TRUE only one item with a given target value can exist on the local
-   *   system. Compare with existingItemId() and uniqueTargets().
-   */
-  public function addMapping($source, $target, $unique = FALSE) {
-    if (!empty($source) && !empty($target)) {
-      $this->config['mappings'][] = array(
-        'source' => $source,
-        'target' => $target,
-        'unique' => $unique,
-      );
-    }
-  }
-
-  /**
-   * Set unique state of a mapping target.
-   */
-  public function setUnique($source, $target, $unique) {
-    if (!empty($source) && !empty($target)) {
-      foreach ($this->config['mappings'] as $k => $mapping) {
-        if ($mapping['source'] == $source && $mapping['target'] == $target) {
-          $this->config['mappings'][$k]['unique'] = $unique;
-        }
-      }
-    }
-  }
-
-  /**
-   * Remove a mapping.
-   */
-  public function removeMapping($source, $target) {
-    foreach ($this->config['mappings'] as $k => $mapping) {
-      if ($mapping['source'] == $source && $mapping['target'] == $target) {
-        unset($this->config['mappings'][$k]);
-      }
-    }
-    // Keep or keys clean.
-    $this->config['mappings'] = array_values($this->config['mappings']);
-  }
-
-  /**
    * Get mappings.
    */
   public function getMappings() {

