Browse Source

Merged 6.x-0.4-dev branch into 6.x-1617096-unify_coding_style branch

laceysanderson 12 years ago
parent
commit
f85504db85

+ 36 - 0
tripal_bulk_loader/tripal_bulk_loader.admin.inc

@@ -43,6 +43,42 @@ function tripal_bulk_loader_admin_template() {
   return $output;
 }
 
+/**
+ * A Configuration form for this module
+ */
+function tripal_bulk_loader_configuration_form($form_state = NULL) {
+  $form = array();
+
+  $form['speed'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Possible Speed Improvements'),
+  );
+
+  $form['speed']['prepare'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use Prepared Statements'),
+    '#description' => t('SQL Prepared Statements allow for SQL queries which will be run '
+      .'many times to be parsed, rewritten and planned only once rather then every time '
+      .'the query is run. In the case of the bulk loader, this ensures that planning only '
+      .'occurs once for each "record" in your bulk loading template.'),
+    '#default_value' => variable_get('tripal_bulk_loader_prepare', TRUE),
+  );
+
+  $form['submit1'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save')
+  );
+
+  return $form;
+}
+
+/**
+ * A Configuration form for this module (Submit)
+ */
+function tripal_bulk_loader_configuration_form_submit($form, $form_state) {
+
+  variable_set('tripal_bulk_loader_prepare', $form_state['values']['prepare']);
+}
 
 //////////////////////////////////////////////////////////////////////////////////////
 // Modify Template

+ 2427 - 0
tripal_bulk_loader/tripal_bulk_loader.admin.inc.orig

@@ -0,0 +1,2427 @@
+<?php
+
+/**
+ * @file
+ * Handles Create/Edit/Delete Template Admin Forms
+ */
+
+/**
+ * Provides a description page and quick links for the bulk loader
+ */
+<<<<<<< HEAD
+function tripal_bulk_loader_admin_template() {
+  $output = '';
+
+  $output .= '<br><h3>Quick Links:</h3>';
+  $output .= l('Create a new bulk loader template', 'admin/tripal/tripal_bulk_loader_template/create') . "<br>";
+  $output .= l('Edit a bulk loader template', 'admin/tripal/tripal_bulk_loader_template/edit') . "<br>";
+  $output .= l('Delete a bulk loader template', 'admin/tripal/tripal_bulk_loader_template/delete') . "<br>";
+  $output .= l('Export a bulk loader template', 'admin/tripal/tripal_bulk_loader_template/export') . "<br>";
+  $output .= l('Import a bulk loader template', 'admin/tripal/tripal_bulk_loader_template/import') . "<br>";
+=======
+function tripal_bulk_loader_admin_template () {
+	$output = '';
+
+	$output .= '<br><h3>Quick Links:</h3>';
+  $output .= l('Create a new bulk loader template', 'admin/tripal/tripal_bulk_loader_template/create')."<br>";
+  $output .= l('Edit a bulk loader template', 'admin/tripal/tripal_bulk_loader_template/edit')."<br>";
+  $output .= l('Delete a bulk loader template', 'admin/tripal/tripal_bulk_loader_template/delete')."<br>";
+  $output .= l('Export a bulk loader template', 'admin/tripal/tripal_bulk_loader_template/export')."<br>";
+  $output .= l('Import a bulk loader template', 'admin/tripal/tripal_bulk_loader_template/import')."<br>";
+>>>>>>> 6.x-0.4-dev
+  $output .= '<br>';
+
+  $output .= '<h3>Module Description:</h3>';
+  $output .= '<p>This module provides the ability to create loading templates for any tab-delimited '
+    . 'data file allowing it to be loaded into chado. The Loading Templates are a direct mapping '
+    . 'between the columns in your file and the columns in chado tables. As such to use this tool '
+    . 'you need to be very familar with the chado schema -See '
+    . l('Chado -Getting Started', 'http://gmod.org/wiki/Chado_-_Getting_Started')
+    . '. The ability to add constants and specify foreign key contraints is also provided '
+    . 'in order for the loader to fill chado columns which may be required but are not specified '
+    . 'in your input file.</p>';
+  $output .= '<br>';
+
+  $output .= '<h3>Setup Instructions</h3>';
+  $output .= '<p>After intallation of the bulk loader module, the following tasks should be performed:</p>';
+  $output .= '<ol>';
+  $output .= '<li><b>Install Theme:</b> In order for Bulk Loading pages to be displayed correctly, '
+    .'the contents of the Tripal Bulk Loader theme directory ([drupal root]/sites/all/modules/tripal/tripal_bulk_loader/theme) '
+    .'should be moved to the base directory of the Tripal theme ([drupal root]/sites/all/themes/tripal). '
+    .'Finally the drupal cache should be cleared for the new theme to take effect -navigate to admin/settings/performance '
+    .'and click the Clear Cached Data button.</li>';
+  $output .= '</ol>';
+
+  return $output;
+}
+
+/**
+ * A Configuration form for this module
+ */
+function tripal_bulk_loader_configuration_form($form_state = NULL) {
+  $form = array();
+
+  $form['speed'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Possible Speed Improvements'),
+  );
+
+  $form['speed']['prepare'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use Prepared Statements'),
+    '#description' => t('SQL Prepared Statements allow for SQL queries which will be run '
+      .'many times to be parsed, rewritten and planned only once rather then every time '
+      .'the query is run. In the case of the bulk loader, this ensures that planning only '
+      .'occurs once for each "record" in your bulk loading template.'),
+    '#default_value' => variable_get('tripal_bulk_loader_prepare', TRUE),
+  );
+
+  $form['submit1'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save')
+  );
+
+  return $form;
+}
+
+/**
+ * A Configuration form for this module (Submit)
+ */
+function tripal_bulk_loader_configuration_form_submit($form, $form_state) {
+
+  variable_set('tripal_bulk_loader_prepare', $form_state['values']['prepare']);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// Modify Template
+//////////////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * The main form reached at admin/tripal/tripal_bulk_loader/create and /edit
+ */
+function tripal_bulk_loader_modify_template_base_form($form_state = NULL, $mode) {
+  $form = array();
+
+   // get template id from path and rebuild form
+   if ($_GET['template_id']) {
+    if (preg_match('/^\d+$/', $_GET['template_id'])) {
+      $form_state['storage']['template_id'] = $_GET['template_id'];
+    }
+
+    $sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+    $result = db_fetch_object(db_query($sql, $form_state['storage']['template_id']));
+    $form_state['storage']['template'] = unserialize($result->template_array);
+    $form_state['storage']['template_name'] = $result->name;
+
+    $form_state['storage']['record2priority'] = array();
+    foreach ($form_state['storage']['template'] as $priority => $record_array) {
+      if (!is_array($record_array)) {
+      continue; }
+      $form_state['storage']['record2priority'][$record_array['record_id']] = $priority;
+    }
+  }
+
+  $form['mode'] = array(
+    '#type' => 'hidden',
+    '#value' => $mode,
+  );
+
+  if ($form_state['storage']['template_id']) {
+    $form['template_name'] = array(
+        '#type' => 'item',
+        '#title' => 'Template',
+        '#value' => $form_state['storage']['template_name'],
+        '#weight' => 1,
+    );
+  }
+  else {
+    if (preg_match('/create/', $mode)) {
+     $form['new_template_name'] = array(
+        '#type' => 'textfield',
+        '#title' => 'Template Name',
+        '#weight' => 1,
+      );
+    }
+    elseif (preg_match('/edit/', $mode)) {
+      $sql = "SELECT * FROM {tripal_bulk_loader_template}";
+      $resource = db_query($sql);
+      $templates = array();
+      $templates[''] = 'Select a Template';
+      while ($r = db_fetch_object($resource)) {
+        $templates[$r->template_id] = $r->name;
+      }
+
+      $form['template_id'] = array(
+        '#title'         => t('Template'),
+        '#description'   => t('Please select the template you would like to edit.'),
+        '#type'          => 'select',
+        '#options'       => $templates,
+        '#default_value' => $form_state['storage']['template_id'],
+        '#weight'        => 0,
+        '#required'      => TRUE,
+        '#weight' => 1,
+      );
+    }
+  }
+
+  $form['records'] = array(
+<<<<<<< HEAD
+    '#type' => ($form_state['storage']['template_id'])? 'fieldset' : 'hidden',
+    '#title' => t('Current Records'),
+    '#collapsible' => TRUE,
+    '#weight' => 2,
+=======
+		'#type' => ($form_state['storage']['template_id'])? 'fieldset' : 'hidden',
+		'#title' => t('Current Records'),
+		'#collapsible' => TRUE,
+		'#weight' => 2,
+>>>>>>> 6.x-0.4-dev
+  );
+
+  $form['records']['description'] = array(
+    '#type' => 'item',
+    '#value' => 'Records will be inserted into the chado database in the order listed below. To '
+      .'change this order: <ul><li>Drag the rows into the correct order OR</li><li>Enter '
+      .'the numbers 1 and up in the Order textboxes to indicate the correct order.</li></ul>',
+  );
+
+  $form['records']['records-data'] = array(
+    '#tree' => TRUE,
+  );
+
+  $form['records']['no_records'] = array(
+    '#type' => 'hidden',
+    '#value' => TRUE,
+  );
+
+  $form['records']['submit-new_record'] = array(
+    '#type' => 'submit',
+    '#value' => 'New Record/Field',
+  );
+
+  $form['records']['submit-reorder'] = array(
+    '#type' => 'submit',
+    '#value' => 'Save Order',
+  );
+
+<<<<<<< HEAD
+  $form['fields'] = array(
+    '#type' => ($form_state['storage']['template_id'])? 'fieldset' : 'hidden',
+    '#title' => t('Current Fields'),
+    '#collapsible' => TRUE,
+    '#weight' => 3,
+  );
+=======
+	$form['fields'] = array(
+		'#type' => ($form_state['storage']['template_id'])? 'fieldset' : 'hidden',
+		'#title' => t('Current Fields'),
+		'#collapsible' => TRUE,
+		'#weight' => 3,
+	);
+>>>>>>> 6.x-0.4-dev
+
+  $form['fields']['fields-data'] = array(
+    '#tree' => TRUE,
+  );
+
+<<<<<<< HEAD
+  if ($form_state['storage']['template']) {
+=======
+	if ($form_state['storage']['template']) {
+>>>>>>> 6.x-0.4-dev
+
+    // List Current Fields -------------------------------------------------------------
+    $i=1;
+    foreach ($form_state['storage']['template'] as $priority => $table_array) {
+<<<<<<< HEAD
+      if (!is_array($table_array)) {
+      continue; }
+=======
+      if (!is_array($table_array)) { continue; }
+>>>>>>> 6.x-0.4-dev
+
+        $form['records']['no_records']['#value'] = FALSE;
+
+        $form['records']['records-data'][$priority] = array(
+          'title' => array(
+            '#type' => 'markup',
+            '#value' => $table_array['record_id'],
+          ),
+          'chado_table' => array(
+            '#type' => 'markup',
+            '#value' => $table_array['table'],
+          ),
+          'mode' => array(
+            '#type' => 'item',
+            '#value' => ($table_array['mode']) ? $table_array['mode'] : 'insert_unique',
+          ),
+          'new_priority' => array(
+            '#type' => 'select',
+            '#options' => range(1, sizeof($form_state['storage']['template'])),
+            '#default_value' => $priority,
+          ),
+          'old_priority' => array(
+            '#type' => 'hidden',
+            '#value' => $priority,
+          ),
+          'id'  => array(
+            '#type' => 'hidden',
+            '#value' => $priority,
+          ),
+          'submit-edit_record' => array(
+            '#type' => 'submit',
+            '#name' => (string)$priority,
+            '#value' => 'Edit Record',
+          ),
+          'submit-add_field' => array(
+            '#type' => 'submit',
+            '#name' => (string)$priority,
+            '#value' => 'Add Field',
+          ),
+          'submit-duplicate_record' => array(
+            '#type' => 'submit',
+            '#name' => (string)$priority,
+            '#value' => 'Duplicate Record'
+          ),
+        );
+
+        foreach ($table_array['fields'] as $field_index => $field) {
+
+          $form['fields']['fields-data'][$i] = array(
+            'record_id' => array(
+              '#type' => 'item',
+              '#value' => $table_array['record_id'],
+            ),
+            'priority_hidden' => array(
+              '#type' => 'hidden',
+              '#value' => $priority,
+            ),
+            'field_name' => array(
+              '#type' => 'item',
+              '#value' => $field['title'],
+            ),
+            'chado_table_name' => array(
+              '#type' => 'item',
+              '#value' => $table_array['table'],
+            ),
+            'chado_table_hidden' => array(
+              '#type' => 'hidden',
+              '#value' => $table_array['table'],
+            ),
+            'chado_field_name' => array(
+              '#type' => 'item',
+              '#value' => $field['field'],
+            ),
+            'sheet_name' => array(
+              '#type' => 'item',
+              '#value' => $field['spreadsheet sheet'],
+            ),
+            'column_num' => array(
+              '#type' => 'item',
+              '#value' => $field['spreadsheet column'],
+            ),
+            'constant_value' => array(
+              '#type' => 'item',
+              '#value' => $field['constant value'],
+            ),
+            'field_index' => array(
+              '#type' => 'hidden',
+              '#value' => $field_index
+            ),
+            'foreign_record_id' => array(
+              '#type' => 'item',
+              '#value' => $field['foreign key'],
+            ),
+            'edit_submit' => array(
+              '#type' => 'submit',
+              '#name' => (string)$i,
+              '#value' => "Edit Field",
+            ),
+            'delete_submit' => array(
+              '#type' => 'submit',
+              '#name' => (string)$i,
+              '#value' => "Delete Field",
+            ),
+          );
+
+          $i++;
+        }
+    }
+    $form['fields']['total_fields'] = array(
+      '#type' => 'item',
+      '#value' => $i,
+    );
+
+  }
+
+  if ($form['records']['no_records']['#value']) {
+    $form['records']['description'] = array(
+      '#type' => 'item',
+      '#value' => 'There are currently no records.',
+    );
+    unset($form['records']['submit-reorder']);
+
+    $form['fields']['description'] = array(
+      '#type' => 'item',
+      '#value' => 'There are currently no fields.',
+    );
+
+  }
+
+<<<<<<< HEAD
+  $mode_title = (preg_match('/create/', $mode)) ? 'Create Template' : 'Edit Template';
+  $value = ($form_state['storage']['template_id'])? 'Save Template' : $mode_title;
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => $value,
+    '#weight' => 4,
+  );
+  return $form;
+=======
+  $mode_title = (preg_match('/create/',$mode)) ? 'Create Template' : 'Edit Template';
+	$value = ($form_state['storage']['template_id'])? 'Save Template' : $mode_title;
+	$form['submit'] = array(
+		'#type' => 'submit',
+		'#value' => $value,
+		'#weight' => 4,
+	);
+
+	return $form;
+>>>>>>> 6.x-0.4-dev
+}
+
+/**
+ * Submit for tripal_bulk_loader_modify_template_base_form
+ */
+function tripal_bulk_loader_modify_template_base_form_submit($form, &$form_state) {
+
+  $form_state['rebuild'] = TRUE;
+  if ($form_state['storage']['template_id']) {
+    $sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+    $result = db_fetch_object(db_query($sql, $form_state['storage']['template_id']));
+    $form_state['storage']['template'] = unserialize($result->template_array);
+  }
+
+  $op = $form_state['values'][ $form_state['clicked_button']['#name'] ];
+  switch ($op) {
+    // Initialize after template is chosen ----------------------------------------
+    case 'Edit Template':
+      $form_state['storage']['template_id'] = $form_state['values']['template_id'];
+
+      $sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+      $result = db_fetch_object(db_query($sql, $form_state['storage']['template_id']));
+      $form_state['storage']['template'] = unserialize($result->template_array);
+      $form_state['storage']['template_name'] = $result->name;
+
+      $form_state['storage']['record2priority'] = array();
+      foreach ($form_state['storage']['template'] as $priority => $record_array) {
+        if (!is_array($record_array)) {
+         continue;
+         }
+        $form_state['storage']['record2priority'][$record_array['record_id']] = $priority;
+      }
+    break;
+
+    case 'Create Template':
+      $record = array(
+        'name' => $form_state['values']['new_template_name'],
+        'template_array' => array(),
+      );
+      drupal_write_record('tripal_bulk_loader_template', $record);
+      $form_state['storage']['template_id'] = $record['template_id'];
+      $form_state['storage']['template_name'] = $record['name'];
+      $form_state['storage']['template'] = array();
+    break;
+
+    // Save Reordered Records -----------------------------------------------------
+    case 'Save Order':
+      $new_template = $form_state['storage']['template'];
+      // unset old elements
+       $form_state['storage']['record2priority'] = array();
+      foreach ($new_template as $priority => $record_array) {
+<<<<<<< HEAD
+        if (preg_match('/\d+/', $priority)) {
+           unset($new_template[$priority]);
+         }
+=======
+        if (preg_match('/\d+/', $priority)) { unset($new_template[$priority]); }
+>>>>>>> 6.x-0.4-dev
+      }
+      //set elements in new order
+      foreach ($form_state['values']['records-data'] as $item) {
+        $new_template[$item['new_priority']] = $form_state['storage']['template'][$item['old_priority']];
+        $record_name = $new_template[$item['new_priority']]['record_id'];
+        $form_state['storage']['record2priority'][$record_name] = $item['new_priority'];
+      }
+      ksort($new_template);
+      $form_state['storage']['template'] = $new_template;
+    break;
+
+    case 'New Record/Field':
+      $query = array(
+<<<<<<< HEAD
+        'template_id' => $form_state['storage']['template_id'],
+=======
+        'template_id'=> $form_state['storage']['template_id'],
+>>>>>>> 6.x-0.4-dev
+        'record_id' => 'NEW',
+      );
+      drupal_goto('admin/tripal/tripal_bulk_loader_template/add_field', $query);
+    break;
+
+    case 'Edit Record':
+      $query = array(
+<<<<<<< HEAD
+        'template_id' => $form_state['storage']['template_id'],
+=======
+        'template_id'=> $form_state['storage']['template_id'],
+>>>>>>> 6.x-0.4-dev
+        'record_id' => $form_state['clicked_button']['#name'],
+      );
+      drupal_goto('admin/tripal/tripal_bulk_loader_template/edit_record', $query);
+    break;
+
+    case 'Add Field':
+      $query = array(
+<<<<<<< HEAD
+        'template_id' => $form_state['storage']['template_id'],
+=======
+        'template_id'=> $form_state['storage']['template_id'],
+>>>>>>> 6.x-0.4-dev
+        'record_id' => $form_state['clicked_button']['#name'],
+      );
+      drupal_goto('admin/tripal/tripal_bulk_loader_template/add_field', $query);
+    break;
+
+    case 'Duplicate Record':
+      // original record (one to be duplicated)
+      $orig_priority = $form_state['clicked_button']['#name'];
+      $record = $form_state['storage']['template'][ $orig_priority ];
+
+      // new record
+      $new_priority = sizeof($form_state['storage']['template']) + 1;
+      $record['record_id'] = $record['record_id'] . '_' . date('YzHi');
+      $form_state['storage']['template'][ $new_priority ] = $record;
+    break;
+
+    case 'Edit Field':
+      $field_data_index = $form_state['clicked_button']['#name'];
+      $query = array(
+<<<<<<< HEAD
+        'template_id' => $form_state['storage']['template_id'],
+=======
+        'template_id'=> $form_state['storage']['template_id'],
+>>>>>>> 6.x-0.4-dev
+        'record_id' => $form_state['values']['fields-data'][$field_data_index]['priority_hidden'],
+        'field_index' => $form_state['values']['fields-data'][$field_data_index]['field_index'],
+      );
+      drupal_goto('admin/tripal/tripal_bulk_loader_template/edit_field', $query);
+    break;
+
+    case 'Delete Field':
+      $field_data = $form_state['values']['fields-data'][$form_state['clicked_button']['#name']];
+      $priority = $field_data['priority_hidden'];
+      $field_key = $field_data['field_index'];
+      unset($form_state['storage']['template'][$priority]['fields'][$field_key]);
+      if (!$form_state['storage']['template'][$priority]['fields']) {
+        unset($form_state['storage']['record2priority'][$form_state['storage']['template'][$priority]['record_id']]);
+        unset($form_state['storage']['template'][$priority]);
+      }
+      drupal_set_message('Deleted Field from Template.');
+    break;
+  } //end of switch
+
+  // Save Template
+  $record = array(
+    'template_id' => $form_state['storage']['template_id'],
+    'template_array' => serialize($form_state['storage']['template'])
+  );
+  drupal_write_record('tripal_bulk_loader_template', $record, array('template_id'));
+  drupal_set_message('Template Saved.');
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// Delete Template
+//////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Delete Template Form
+ * This form allows admin to delete already existing templates
+ */
+function tripal_bulk_loader_delete_template_base_form() {
+  $form = array();
+
+  $sql = "SELECT * FROM {tripal_bulk_loader_template}";
+  $resource = db_query($sql);
+  $templates = array();
+  $templates[''] = 'Select a Template';
+  while ($r = db_fetch_object($resource)) {
+    $templates[$r->template_id] = $r->name;
+  }
+  $form['template_name'] = array(
+      '#title'         => t('Template'),
+      '#description'   => t('Please select the template you would like to delete.'),
+      '#type'          => 'select',
+      '#options'       => $templates,
+      '#weight'        => 0,
+      '#required'      => TRUE,
+<<<<<<< HEAD
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => 'Delete Template',
+  );
+
+  return $form;
+=======
+	);
+
+	$form['submit'] = array(
+		'#type' => 'submit',
+		'#value' => 'Delete Template',
+	);
+
+	return $form;
+>>>>>>> 6.x-0.4-dev
+}
+
+/**
+ * Delete Template Form Submit
+ *
+ * @param $form
+ *   The form that was submitted
+ * @param $form_state
+ *   The values and storage that were submitted
+ */
+function tripal_bulk_loader_delete_template_base_form_submit($form, &$form_state) {
+  $sql = "DELETE FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+  db_query($sql, $form_state['values']['template_name']);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// Import/Export Template
+//////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Import/Export Template Form
+ *
+ * On export, simply selects the serialized array from the db for a given template
+ * and presents it to the user. On import, a serialized template array and a name is
+ * supplied and a template record is created.
+ *
+ * @todo Make array presented to the user more readable. (ie: unserialize and print to the screen)
+ *
+ * @param $form_state
+ *   The values and storage for the form
+ * @param $mode
+ *   Either 'import' or 'export' to indicate which function is being performed
+ * @return
+ *   A form array to be rendered by drupal_get_form
+ */
+function tripal_bulk_loader_import_export_template_form($form_state = NULL, $mode) {
+  $form = array();
+
+  $form['mode'] = array(
+    '#type' => 'hidden',
+    '#value' => $mode,
+  );
+
+  if (preg_match('/import/', $mode)) {
+   $form['new_template_name'] = array(
+      '#type' => 'textfield',
+      '#title' => 'Template Name',
+      '#weight' => 1,
+    );
+  }
+  elseif (preg_match('/export/', $mode)) {
+    $sql = "SELECT * FROM {tripal_bulk_loader_template}";
+    $resource = db_query($sql);
+    $templates = array();
+    $templates[''] = 'Select a Template';
+    while ($r = db_fetch_object($resource)) {
+      $templates[$r->template_id] = $r->name;
+    }
+
+    $form['template_id'] = array(
+      '#title'         => t('Template'),
+      '#description'   => t('Please select the template you would like to edit.'),
+      '#type'          => 'select',
+      '#options'       => $templates,
+      '#default_value' => $form_state['storage']['template_id'],
+      '#weight'        => 0,
+      '#required'      => TRUE,
+      '#weight' => 1,
+    );
+  }
+
+  $form['template_array'] = array(
+    '#type' => 'textarea',
+    '#title' => 'Template Array',
+    '#default_value' => $form_state['storage']['template_array'],
+    '#weight' => 2,
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => 'Submit',
+    '#weight' => 10,
+  );
+
+  return $form;
+}
+
+/**
+ * Import/Export Template Form Submit
+ *
+ * @param $form
+ *   The form that was submitted
+ * @param $form_state
+ *   The values and storage that were submitted
+ */
+function tripal_bulk_loader_import_export_template_form_submit($form, &$form_state) {
+  switch ($form_state['values']['mode']) {
+    case 'export':
+      $record = db_fetch_object(db_query("SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d", $form_state['values']['template_id']));
+      $form_state['storage']['template_array'] = $record->template_array;
+      $form_state['storage']['template_id'] = $form_state['values']['template_id'];
+    break;
+    case 'import':
+      $record = array(
+        'name' => $form_state['values']['new_template_name'],
+        'template_array' => $form_state['values']['template_array'],
+      );
+      drupal_write_record('tripal_bulk_loader_template', $record);
+      if ($record->template_id) {
+        drupal_set_message('Successfully imported Tripal Bulk Loader Template.');
+      }
+    break;
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// Edit Record Form
+//////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edit Record Form
+ *
+ * This form is meant to be called from a bulk loader form. The following should be set
+ * in the query section of the path:
+ *  - template_id=\d+: the template which the edited record is part of
+ *  - record_id=\d+: the priority or key in the template array of the record to be edited
+ *
+ * @param $form_state
+ *   Contains the values and storage for the form
+ * @return
+ *   A form array to be rendered by drupal_get_form
+ */
+<<<<<<< HEAD
+function tripal_bulk_loader_edit_template_record_form(&$form_state = NULL) {
+   $form['#cache'] = TRUE; // Make sure the form is cached.
+
+   // get template id from path
+   $template_id = ($_GET['template_id'] !== NULL) ? $_GET['template_id'] : $form_state['values']['template_id'];
+
+   // if there is no template supplied don't return rest of form
+   if (!$template_id) {
+     return $form;
+   }
+=======
+function tripal_bulk_loader_edit_template_record_form (&$form_state = NULL) {
+ 	$form['#cache'] = TRUE; // Make sure the form is cached.
+
+ 	// get template id from path
+ 	$template_id = ($_GET['template_id'] !== NULL) ? $_GET['template_id'] : $form_state['values']['template_id'];
+
+ 	// if there is no template supplied don't return rest of form
+ 	if (!$template_id) {
+ 	  return $form;
+ 	}
+>>>>>>> 6.x-0.4-dev
+
+  // Pre-process values/defaults ---------------------------
+
+   // If this is the first load of the form (no form state) we need to initialize some variables
+   if (!$form_state['storage']['template']) {
+    $sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+    $template = db_fetch_object(db_query($sql, $template_id));
+    $form_state['storage']['template_array'] = unserialize($template->template_array);
+    $form_state['storage']['template'] = $template;
+
+    $form_state['storage']['record2priority'] = array();
+    foreach ($form_state['storage']['template_array'] as $priority => $record_array) {
+      if (!is_array($record_array)) {
+         continue;
+       }
+      $form_state['storage']['record2priority'][$record_array['record_id']] = $priority;
+    }
+
+    $form_state['storage']['referring URL'] = $_SERVER["HTTP_REFERER"];
+  }
+  else {
+    $template = $form_state['storage']['template'];
+  }
+
+   // get the record_id from the path
+   if ($_GET['record_id'] !== NULL) {
+     $form_state['values']['field_group'] = $_GET['record_id'];
+     $form_state['storage']['original_priority'] = $_GET['record_id'];
+  }
+
+
+  // Tables and default table
+  $tables = tripal_core_get_chado_tables();
+  if ($form_state['values']['chado_table']) {
+    $table = $form_state['values']['chado_table'];
+<<<<<<< HEAD
+  }
+  else {
+=======
+  } else {
+>>>>>>> 6.x-0.4-dev
+    $table = $form_state['storage']['template_array'][$form_state['storage']['original_priority']]['table'];
+  }
+
+  //dpm($form_state, 'form state');
+
+<<<<<<< HEAD
+   // Form Proper -------------------------------------------
+=======
+ 	// Form Proper -------------------------------------------
+>>>>>>> 6.x-0.4-dev
+  $form['template_name'] = array(
+    '#type' => 'item',
+    '#title' => 'Template',
+    '#value' => $template->name,
+  );
+
+  $form['template_id'] = array(
+    '#type' => 'hidden',
+    '#value' => $template_id,
+  );
+
+  $form['edit_record'] = array(
+    '#type' => 'fieldset',
+  );
+
+  // check template array for records then add one more
+  if (!$form_state['storage']['record2priority']) {
+    $groups = array();
+  }
+  else {
+    $groups = array_flip($form_state['storage']['record2priority']);
+  }
+  $priority_default = $form_state['values']['field_group'];
+  $form['edit_record']['field_group']  = array(
+    '#type' => 'select',
+    '#title' => 'Record',
+    '#description' => 'By Changing the record here, you can move all the fields from the current record into the selected record.',
+    '#options' => $groups,
+    '#default_value' => $priority_default,
+    '#required' => TRUE,
+  );
+
+  $form['edit_record']['record_name'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Unique Record Name',
+    '#default_value' => $groups[$priority_default],
+  );
+
+  $form['edit_record']['chado_table'] = array(
+    '#type' => 'select',
+    '#title' => t('Chado Table'),
+    '#description' => 'This changes the chado table for all fields in this record.',
+    '#options' => $tables,
+    '#default_value' => $table,
+  );
+
+  $form['edit_record']['mode'] = array(
+    '#type' => 'radios',
+    '#title' => 'Action to take when Loading Record',
+    '#options' => array(
+      'select' => 'SELECT: Don\'t insert this record: it\'s used to define a foreign key in another record',
+      'insert' => 'INSERT: Insert the record',
+      'optional' => 'OPTIONAL: Record will only be inserted if all required data is filled in',
+      'insert_once' => 'INSERT ONCE: Record will be inserted once for the entire spreadsheet',
+      'insert_unique' => 'INSERT UNIQUE: Only insert record if there isn\'t a record with the same values',
+    ),
+    '#default_value' => 'insert_unique'
+  );
+
+  $form['edit_record']['submit-edit_record'] = array(
+      '#type' => 'submit',
+      '#value' => 'Edit Record'
+  );
+
+  $form['edit_record']['submit-cancel'] = array(
+      '#type' => 'submit',
+      '#value' => 'Cancel'
+  );
+
+  return $form;
+}
+
+
+/**
+ * Edit Record Form Submit
+ *
+ * @param $form
+ *   The form that was submitted
+ * @param $form_state
+ *   Contains the values and storage for the form
+ */
+function tripal_bulk_loader_edit_template_record_form_submit($form, &$form_state) {
+  //dpm($form_state, 'form state -start submit');
+
+  if (!$form_state['ahah_submission']) {
+    if ($form_state['values']['op'] ==  'Edit Record') {
+
+      $template = $form_state['storage']['template_array'];
+
+      // Edit Record
+      $record = $template[ $form_state['storage']['original_priority'] ];
+      $record['record_id'] = $form_state['values']['record_name'];
+      $record['mode'] = $form_state['values']['mode'];
+      $record['table'] = $form_state['values']['chado_table'];
+
+      if ($form_state['storage']['original_priority'] != $form_state['values']['field_group']) {
+        $record['fields'] = array_merge($record['fields'], $template[ $form_state['values']['field_group'] ]['fields']);
+        $template[ $form_state['values']['field_group'] ] = $record;
+        unset($template[ $form_state['storage']['original_priority'] ]);
+      }
+      else {
+        $template[ $form_state['storage']['original_priority'] ] = $record;
+      }
+
+      // Save Template
+      $form_state['storage']['template']->template_array = serialize($template);
+      $success = drupal_write_record('tripal_bulk_loader_template', $form_state['storage']['template'], array('template_id'));
+
+      if ($success) {
+        drupal_set_message('Successfully Updated Template Record');
+        drupal_set_message('Template Saved.');
+
+<<<<<<< HEAD
+        $path = explode('?', $form_state['storage']['referring URL']);
+=======
+        $path = explode('?',$form_state['storage']['referring URL']);
+>>>>>>> 6.x-0.4-dev
+        parse_str($path[1], $query);
+        $query['template_id'] = $form_state['storage']['template']->template_id;
+        drupal_goto($path[0], $query);
+      }
+      else {
+        drupal_set_message('Unable to Save Template!', 'error');
+        watchdog('T_bulk_loader',
+          'Unable to save bulk loader template: %template',
+          array('%template' => print_r($form_state['storage']['template'], TRUE)),
+          WATCHDOG_ERROR
+        );
+      }
+    }
+    elseif ($form_state['values']['op'] ==  'Cancel') {
+        $path = explode('?', $form_state['storage']['referring URL']);
+        parse_str($path[1], $query);
+        $query['template_id'] = $form_state['storage']['template']->template_id;
+        //dpm('Redirecting to: '.$path[0].'?'.print_r($query,TRUE).' where the referring URL:'.$form_state['storage']['referring URL']);
+        drupal_goto($path[0], $query);
+    }
+  }
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// Add/Edit Field Forms
+//////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Add Field Form
+ *
+ * This form is meant to be called from a bulk loader form. Blank Defaults are in place but you
+ * can use the following in the query of the path to set defaults for a given template:
+ *  - template_id=\d+: the template to add the field to
+ *  - record_id=\d+: the priority or key in the template array of the record to add the field to
+ *
+ * @param $form_state
+ *   Contains the values and storage for the form
+ * @return
+ *   A form array to be rendered by drupal_get_form
+ */
+function tripal_bulk_loader_add_template_field_form(&$form_state = NULL) {
+  $form = array();
+<<<<<<< HEAD
+   $form['#cache'] = TRUE; // Make sure the form is cached.
+
+   // get template id from path
+   $template_id = ($_GET['template_id']) ? $_GET['template_id'] : $form_state['values']['template_id'];
+
+   // if there is no template supplied don't return rest of form
+   if (!$template_id) {
+     return $form;
+   }
+=======
+ 	$form['#cache'] = TRUE; // Make sure the form is cached.
+
+ 	// get template id from path
+ 	$template_id = ($_GET['template_id']) ? $_GET['template_id'] : $form_state['values']['template_id'];
+
+ 	// if there is no template supplied don't return rest of form
+ 	if (!$template_id) {
+ 	  return $form;
+ 	}
+>>>>>>> 6.x-0.4-dev
+
+  // Pre-set Variables needed for form proper------------------------------------------
+
+   // If this is the first load of the form (no form state) we need to initialize some variables
+   if (!$form_state['storage']['template']) {
+    $sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+    $template = db_fetch_object(db_query($sql, $template_id));
+    $form_state['storage']['template_array'] = unserialize($template->template_array);
+    $form_state['storage']['template'] = $template;
+
+    $form_state['storage']['record2priority'] = array();
+    foreach ($form_state['storage']['template_array'] as $priority => $record_array) {
+      if (!is_array($record_array)) {
+        continue;
+      }
+      $form_state['storage']['record2priority'][$record_array['record_id']] = $priority;
+    }
+
+    $form_state['storage']['referring URL'] = $_SERVER["HTTP_REFERER"];
+  }
+  else {
+    $template = $form_state['storage']['template'];
+  }
+
+  $field_type = ($form_state['values']['field_type'])? $form_state['values']['field_type'] : 'table field';
+
+  // Tables and default table
+  $tables = tripal_core_get_chado_tables();
+  if ($form_state['values']) {
+    if (!preg_match('/^' . current($tables) . '$/', $form_state['values']['chado_table'])) {
+      $table = $form_state['values']['chado_table'];
+    }
+    elseif ($form_state['values']['record_name']) {
+      $record_name = $form_state['values']['record_name'];
+      $priority = $form_state['storage']['record2priority'][$record_name];
+      $table = $form_state['storage']['template_array'][$priority]['table'];
+    }
+    else {
+      $priority = $form_state['values']['field_group'];
+      $table = $form_state['storage']['template_array'][$priority]['table'];
+    }
+  }
+  if (!$table) {
+    $table = reset($tables);
+  }
+
+   // get the record_id from the path
+   if ($_GET['record_id'] !== NULL) {
+     $form_state['values']['field_group'] = $_GET['record_id'];
+    if (preg_match('/\d+/', $_GET['record_id'])) {
+      $priority = $form_state['values']['field_group'];
+      $table = $form_state['storage']['template_array'][$priority]['table'];
+    }
+  }
+
+  // Fields and foreign key mappings
+  $chado_fields = array();
+  $fk_options = array();
+  $fk_options['NULL'] = 'None';
+  $table_description = module_invoke_all('chado_' . $table . '_schema');
+  //dpm($table_description, 'table description for |'.$table.'|');
+  if ($field_type == 'foreign key') {
+    $foreign_field2table = array();
+    foreach ($table_description['foreign keys'] as $key_table => $key_array) {
+      foreach ($key_array['columns'] as $left_field => $right_field) {
+        $chado_fields[$left_field] = $left_field;
+        $foreign_field2table[$left_field] = $key_table;
+      }
+    }
+    reset($chado_fields);
+
+    // set default field
+    if (empty($chado_fields)) {
+      $field = NULL;
+    }
+    elseif ($chado_fields[$form_state['values']['chado_field']]) {
+      $field = $form_state['values']['chado_field'];
+    }
+    else {
+      $field = current($chado_fields);
+    }
+
+    // Foreign key options
+    $foreign_table = $foreign_field2table[$field];
+    if ($foreign_table) {
+      foreach ($form_state['storage']['record2priority'] as $record_name => $priority ) {
+        if (preg_match('/^' . $foreign_table . '$/', $form_state['storage']['template_array'][$priority]['table'])) {
+          $fk_options[$record_name] = $record_name;
+        }
+      }
+    }
+  }
+  else {
+    foreach ($table_description['fields'] as $field_name => $field_array) {
+        $chado_fields[$field_name] = $field_name;
+    }
+  }
+
+  $variables = array(
+    'form_state' => $form_state,
+    'tables' => $tables,
+    'default table' => $table,
+    'fields' => $chado_fields,
+    'default_field' => $field,
+    'priority' => $priority,
+    'record_name' => $record_name,
+    'table description' => $table_description,
+    'foreign key options' => $fk_options,
+    'foreign field=>table' => $foreign_field2table,
+    'foreign table' => $foreign_table,
+  );
+  //dpm($variables, 'variables');
+
+  // Start of Form Proper--------------------------------------------------------------
+  //dpm($form_state, 'Form State');
+
+  $form['template_name'] = array(
+    '#type' => 'item',
+    '#title' => 'Template',
+    '#value' => $template->name,
+  );
+
+  $form['template_id'] = array(
+    '#type' => 'hidden',
+    '#value' => $template_id,
+  );
+
+  $form['add_fields'] = array(
+    '#type' => 'fieldset',
+    '#prefix' => '<div id="tripal_bulk_loader_template-add_field">',
+    '#suffix' => '</div>',
+  );
+
+  $form['add_fields']['field_type'] = array(
+    '#type' => 'radios',
+    '#title' => t('Type of Field'),
+    '#options' => array(
+      'table field' => t('Spreadsheet: Fields which maps to a Spreadsheet Column'),
+      'constant' => t('Constant: Field which remains Constant throughout the Spreadsheet'),
+      'foreign key' => t('Foreign Key: Fields which map to a record in another table'),
+    ),
+    '#required' => TRUE,
+    '#default_value' => $field_type,
+    '#ahah' => array(
+      'path' => 'admin/tripal/tripal_bulk_loader_template/add_field_ahah',
+      'wrapper' => 'tripal_bulk_loader_template-add_field',
+      'effect' => 'fade'
+    ),
+  );
+
+  // check template array for records then add one more
+  if (!$form_state['storage']['record2priority']) {
+    $groups = array();
+  }
+  else {
+    $groups = array_flip($form_state['storage']['record2priority']);
+  }
+  $groups['NONE'] = 'Select a Record';
+  $groups['NEW'] = 'New Record';
+  $form['add_fields']['field_group']  = array(
+    '#type' => 'select',
+    '#title' => 'Record',
+    '#description' => 'This is used to group a set of fields together allowing '
+      .'multiple records to be inserted into the same table per line of the spreadsheet',
+    '#options' => $groups,
+    '#default_value' => (preg_match('/\w+.*/', $form_state['values']['field_group'])) ? $form_state['values']['field_group'] : 'NONE',
+    '#ahah' => array(
+      'path' => 'admin/tripal/tripal_bulk_loader_template/add_field_ahah',
+      'wrapper' => 'tripal_bulk_loader_template-add_field',
+      'effect' => 'fade'
+    ),
+    '#required' => TRUE,
+  );
+
+  $form['add_fields']['record_name'] = array(
+    '#type' => (preg_match('/NEW/', $form_state['values']['field_group'])) ? 'textfield' : 'hidden',
+    '#title' => 'Unique Record Name',
+    '#prefix' => '<div id="tripal_bulk_loader_template-add_record">',
+    '#suffix' => '</div>',
+    '#default_value' => $form_state['values']['record_name'],
+  );
+
+  $form['add_fields']['field_title'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Human-readable Title for Field'),
+    '#default_value' => $form_state['values']['field_title'],
+  );
+
+  // Spreadsheet column
+  $form['add_fields']['columns'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Spreadsheet Column'),
+    '#collapsible' => TRUE,
+    '#collapsed' => ($field_type == 'table field')? FALSE : TRUE,
+  );
+
+  $form['add_fields']['columns']['sheet_name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Worksheet'),
+    '#description' => t('Specify the name of the worksheet.'),
+    '#size' => 5,
+    '#default_value' => ($form_state['values']['sheet_name'])? $form_state['values']['sheet_name'] : 'Sheet1',
+  );
+
+  $form['add_fields']['columns']['column_number'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Column'),
+    '#description' => t('Specify the column in the spreadsheet that this field maps to where the first column is 1.'),
+    '#size' => 5,
+    '#default_value' => $form_state['values']['column_number'],
+  );
+
+  $form['add_fields']['columns']['column_exposed'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Allow Column to be set for each Bulk Loading Job'),
+    '#description' => t('Adds a textbox field to the Bulk Loader Page to allow users to set this value.'),
+    '#default_value' => ($form_state['values']['column_exposed']) ? $form_state['values']['column_exposed'] : $template_field['exposed'],
+  );
+
+  $form['add_fields']['columns']['column_exposed_desc'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Description for exposed field on bulk loading job'),
+    '#description' => t('This description should tell the user what column should be entered here.'),
+    '#default_value' => ($form_state['values']['column_exposed_desc']) ? $form_state['values']['column_exposed_desc'] : $template_field['exposed_description'],
+  );
+
+  // Global Value
+  $form['add_fields']['constant'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Constant'),
+    '#collapsible' => TRUE,
+    '#collapsed' => ($field_type == 'constant')? FALSE : TRUE,
+  );
+
+  $form['add_fields']['constant']['constant_value'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Constant Value'),
+    '#description' => t('Specify the value you wish this field to have regardless of spreadsheet data.'),
+    '#default_value' => $form_state['values']['constant_value']
+  );
+
+  $form['add_fields']['constant']['constant_exposed'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Allow Constant to be set for each Bulk Loading Job'),
+    '#description' => t('Adds a textbox field to the Create Bulk Loader Form to allow users to set this value.')
+  );
+
+  $form['add_fields']['constant']['constant_validate'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Ensure value is in table'),
+    '#description' => t('Checks the database when a bulk loading job is created to ensure the value entered already exists in the database.'),
+  );
+
+  // Foreign Key
+  $form['add_fields']['foreign_key'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Foreign Key',
+    '#collapsible' => TRUE,
+    '#collapsed' => ($field_type == 'foreign key')? FALSE : TRUE,
+  );
+
+  $form['add_fields']['foreign_key']['foreign_record'] = array(
+    '#type' => 'select',
+    '#title' => 'Record to refer to',
+    '#descripion' => 'Select the record that this foreign key shouold refer to. The record needs to already exist and be of the correct table.',
+    '#options' => $fk_options,
+  );
+
+  // Chado Field
+  $form['add_fields']['chado'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Chado Field/Column Details'),
+    '#description' => t('Specify the Table/Field in chado that this field maps to.'),
+  );
+
+  $form['add_fields']['chado']['chado_table'] = array(
+    '#type' => 'select',
+    '#title' => t('Chado Table'),
+    '#options' => $tables,
+    '#default_value' => $table,
+    '#ahah' => array(
+      'path' => 'admin/tripal/tripal_bulk_loader_template/add_field_ahah',
+      'wrapper' => 'tripal_bulk_loader_template-add_field',
+      'effect' => 'fade'
+      ),
+  );
+
+  $form['add_fields']['chado']['chado_field'] = array(
+    '#type' => 'select',
+    '#title' => t('Chado Field/Column'),
+    '#options' => $chado_fields,
+    '#default_value' => $form_state['values']['chado_field'],
+    '#ahah' => array(
+      'path' => 'admin/tripal/tripal_bulk_loader_template/add_field_ahah',
+      'wrapper' => 'tripal_bulk_loader_template-add_field',
+      'effect' => 'fade'
+    ),
+  );
+
+  $form['add_fields']['additional'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Additional Options',
+  );
+
+  $form['add_fields']['additional']['required'] = array(
+    '#type' => 'checkbox',
+    '#title' => 'Make this file required',
+  );
+
+  $form['add_fields']['additional']['regex_transform'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Transform Spreadsheet Value Rules',
+    '#collapsible' => TRUE,
+    '#collapsed' => (!$form_state['storage']['regex']['pattern']) ? TRUE : FALSE,
+  );
+
+  $form['add_fields']['additional']['regex_transform']['regex_description'] = array(
+    '#type' => 'item',
+    '#value' => 'A transformation rule allows you to transform the original value '
+      .'(usually from a user submitted spreadsheet) into the form you would like it stored '
+      .'in the chado database. Each rule consists of a match pattern (a php regular expression '
+      .'which determines which replacement patterns are applied and captures regions of the '
+      .'original value) and a replacement pattern (a string which may contain capture references '
+      .'that describes what the new value should be). Each rule is applied to the result of the '
+      .'previous rule.'
+  );
+
+  $form['add_fields']['additional']['regex_transform']['regex-data'] = array(
+    '#tree' => TRUE,
+  );
+  if (!$form_state['storage']['regex']['pattern']) {
+    $form_state['storage']['regex']['pattern'] = array();
+  }
+  foreach ($form_state['storage']['regex']['pattern'] as $index => $pattern) {
+    $data_element = array(
+      'pattern' => array(
+        '#type' => 'item',
+        '#value' => $pattern,
+      ),
+      'replace' => array(
+        '#type' => 'item',
+        '#value' => $form_state['storage']['regex']['replace'][$index],
+      ),
+      'old_index' => array(
+        '#type' => 'hidden',
+        '#value' => $index,
+      ),
+      'new_index' => array(
+        '#type' => 'select',
+        '#options' => range(0, sizeof($form_state['storage']['regex']['pattern'])-1),
+        '#default_value' => $index,
+      ),
+      'id' => array(
+        '#type' => 'hidden',
+        '#value' => $index,
+      ),
+      'submit-delete' => array(
+        '#type' => 'submit',
+        '#value' => 'Delete Transformation',
+        '#name' => $index,
+      ),
+    );
+    $form['add_fields']['additional']['regex_transform']['regex-data'][$index] = $data_element;
+  }
+
+  $form['add_fields']['additional']['regex_transform']['submit-reorder_regex'] = array(
+    '#type' => ($form_state['storage']['regex']['pattern']) ? 'submit' : 'hidden',
+    '#value' => 'Save Transformation Rule Order'
+  );
+
+  $form['add_fields']['additional']['regex_transform']['new_regex'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Add a new Transformation Rule',
+  );
+
+  $form['add_fields']['additional']['regex_transform']['new_regex']['pattern'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Match Pattern',
+    '#description' => 'You can use standard php regular expressions in this field to specify a '
+      .'pattern. Only if this pattern matches the value in the spreadsheet does the replacement '
+      .'pattern get applied to the value. To capture a section of your value for use in the '
+      .'replacement patten surround with round brackets. For example, <i>GI:(\d+)</i> will match '
+      .' NCBI gi numbers and will capture the numerical digits for use in the replacement pattern. '
+      .' To match and capture any value use <i>.*</i>',
+  );
+
+  $form['add_fields']['additional']['regex_transform']['new_regex']['replace'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Replacement Pattern',
+    '#description' => 'This pattern should contain the text you want to replace the match pattern '
+    .'mentioned above. It can include references of the form \n where n is the number of the '
+    .'capture in the match pattern. For example, \1 will be replaced with the text matched in your '
+    .'first set of round brackets.',
+  );
+
+  if ($field_type == 'table field') {
+    $tab = '&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp';
+    $form['add_fields']['additional']['regex_transform']['new_regex']['replace']['#description'] .= '<p>'
+      .'The following references are also available for spreadsheet fields: <b><#column:<i>number</i>#></b>. '
+      .'This allows you to substitute other spreadsheet values into the current field. For example, '
+      .'if you had the following line:<br>'
+      . $tab . 'SNP' . $tab . '15-Jan-2011' . $tab . '1' . $tab . '54' . $tab . 'Contig34355'
+      .'<br> and your current field is for column #1 and you\'re inserting into the chado field '
+      .'feature.uniquename then you might want to add in the data to ensure your uniquename is '
+      .'unique. The Match Pattern is (.*) to select all the first column and the Replacement '
+      .'Pattern could be \1_<#column:2#> which would insert SNP_15-Jan-2011 into the database.</p>';
+  }
+
+  $form['add_fields']['additional']['regex_transform']['new_regex']['submit-add_transform'] = array(
+    '#type' => 'submit',
+    '#value' => 'Add Transformation',
+  );
+
+  $form['add_fields']['additional']['regex_transform']['test_regex'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Test Transformation Rules',
+  );
+
+  $form['add_fields']['additional']['regex_transform']['test_regex']['test_string'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Test Value',
+    '#description' => 'This should be a value that you expect the above transformation rules '
+      .'to be applied to.',
+    '#default_value' => $form_state['storage']['test_regex_test'],
+  );
+
+  $form['add_fields']['additional']['regex_transform']['test_regex']['test_result'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Test Result',
+    '#description' => 'This is the value that would be saved to the database after the above transformation '
+      .'riles were applied to the Test Value.',
+    '#default_value' => $form_state['storage']['test_regex_result'],
+  );
+
+  $form['add_fields']['additional']['regex_transform']['test_regex']['submit-test'] = array(
+    '#type' => 'submit',
+    '#value' => 'Test Transformation Rules'
+  );
+
+  $form['add_fields']['submit-add_field'] = array(
+      '#type' => 'submit',
+      '#value' => 'Add Field'
+  );
+
+  $form['add_fields']['submit-cancel'] = array(
+      '#type' => 'submit',
+      '#value' => 'Cancel'
+  );
+
+  return $form;
+}
+
+/**
+ * Add Field Submit
+ *
+ * @param $form
+ *   The form that was submitted
+ * @param $form_state
+ *   The values and storage for the form
+ */
+<<<<<<< HEAD
+function tripal_bulk_loader_add_template_field_form_submit($form, &$form_state) {
+=======
+function tripal_bulk_loader_add_template_field_form_submit ($form, &$form_state) {
+>>>>>>> 6.x-0.4-dev
+
+  $op = $form_state['values'][ $form_state['clicked_button']['#name'] ];
+
+  if (!$form_state['ahah_submission']) {
+    if ($op ==  'Add Field') {
+
+      $template = $form_state['storage']['template_array'];
+
+       // If new record
+      if (preg_match('/NEW/', $form_state['values']['field_group'])) {
+        $record_name = $form_state['values']['record_name'];
+        $priority = sizeof($form_state['storage']['template_array']) + 1;
+        $record2priority[$record_name] = $priority;
+        $template[$priority]['table'] = $form_state['values']['chado_table'];
+        $template[$priority]['record_id'] = $record_name;
+
+<<<<<<< HEAD
+      }
+      else {
+=======
+      } else {
+>>>>>>> 6.x-0.4-dev
+        $priority = $form_state['values']['field_group'];
+        $record_name = $record2priority[$priority];
+      }
+
+      // Add field to template array
+      if ($form_state['values']['field_type'] == 'table field') {
+        $field = array(
+          'type' => 'table field',
+          'title' => $form_state['values']['field_title'],
+          'field' => $form_state['values']['chado_field'],
+          'required' => $form_state['values']['required'],
+          //'allowed values' => empty by default,
+          'spreadsheet sheet' => $form_state['values']['sheet_name'],
+          'spreadsheet column' => $form_state['values']['column_number'],
+          'exposed' => $form_state['values']['column_exposed'],
+          'exposed_description' => $form_state['values']['column_exposed_desc'],
+        );
+      }
+      elseif ($form_state['values']['field_type'] == 'constant') {
+        $field = array(
+          'type' => 'constant',
+          'title' => $form_state['values']['field_title'],
+          'field' => $form_state['values']['chado_field'],
+          'required' => $form_state['values']['required'],
+          //'allowed values' => empty by default,
+          'constant value' => $form_state['values']['constant_value'],
+          'exposed' => $form_state['values']['constant_exposed'],
+          'exposed_validate' => $form_state['values']['constant_validate'],
+        );
+<<<<<<< HEAD
+      }
+      elseif ($form_state['values']['field_type'] == 'foreign key') {
+=======
+      } elseif ($form_state['values']['field_type'] == 'foreign key') {
+>>>>>>> 6.x-0.4-dev
+        $field = array(
+          'type' => 'foreign key',
+          'title' => $form_state['values']['field_title'],
+          'field' => $form_state['values']['chado_field'],
+          'foreign key' => $form_state['values']['foreign_record'],
+          'required' => $form_state['values']['required'],
+        );
+      }
+
+      // Deal with any additional options
+      if ($form_state['storage']['regex']) {
+        $field['regex'] = $form_state['storage']['regex'];
+      }
+
+      // Save Template
+      $template[$priority]['fields'][] = $field;
+      $form_state['storage']['template']->template_array = serialize($template);
+      $success = drupal_write_record('tripal_bulk_loader_template', $form_state['storage']['template'], array('template_id'));
+
+      if ($success) {
+        drupal_set_message('Successfully Added Field to Template');
+        drupal_set_message('Template Saved.');
+
+<<<<<<< HEAD
+        $path = explode('?', $form_state['storage']['referring URL']);
+=======
+        $path = explode('?',$form_state['storage']['referring URL']);
+>>>>>>> 6.x-0.4-dev
+        parse_str($path[1], $query);
+        $query['template_id'] = $form_state['storage']['template']->template_id;
+        drupal_goto($path[0], $query);
+      }
+      else {
+        drupal_set_message('Unable to Save Template!', 'error');
+        watchdog('T_bulk_loader',
+          'Unable to save bulk loader template: %template',
+          array('%template' => print_r($form_state['storage']['template'], TRUE)),
+          WATCHDOG_ERROR
+        );
+      }
+    }
+    elseif ($op ==  'Cancel') {
+        $path = explode('?', $form_state['storage']['referring URL']);
+        parse_str($path[1], $query);
+        $query['template_id'] = $form_state['storage']['template']->template_id;
+        drupal_goto($path[0], $query);
+<<<<<<< HEAD
+    }
+    elseif ($op == 'Add Transformation') {
+=======
+    } elseif ($op == 'Add Transformation') {
+>>>>>>> 6.x-0.4-dev
+
+      // Add transformation rule to original field
+      $form_state['storage']['regex']['pattern'][] = '/' . $form_state['values']['pattern'] . '/';
+      $form_state['storage']['regex']['replace'][] = $form_state['values']['replace'];
+      drupal_set_message('Successfully Added Transformation Rule');
+
+<<<<<<< HEAD
+    }
+    elseif ($op == 'Save Transformation Rule Order') {
+=======
+    } elseif ($op == 'Save Transformation Rule Order') {
+>>>>>>> 6.x-0.4-dev
+
+      // Generate new regex array
+      $new_regex = array();
+      $old_regex = $form_state['storage']['regex'];
+      foreach ($form_state['values']['regex-data'] as $key => $element) {
+        $new_regex['pattern'][ $element['new_index'] ] = $old_regex['pattern'][ $element['old_index'] ];
+        $new_regex['replace'][ $element['new_index'] ] = $old_regex['replace'][ $element['old_index'] ];
+      }
+
+      // sort new regex arrays
+      asort($new_regex['pattern']);
+      asort($new_regex['replace']);
+
+      $form_state['storage']['regex'] = $new_regex;
+<<<<<<< HEAD
+    }
+    elseif ($op == 'Delete Transformation') {
+=======
+    } elseif ($op == 'Delete Transformation') {
+>>>>>>> 6.x-0.4-dev
+
+      // Unset regex rule
+      $index = $form_state['clicked_button']['#name'];
+      unset($form_state['storage']['regex']['pattern'][$index]);
+      unset($form_state['storage']['regex']['replace'][$index]);
+
+<<<<<<< HEAD
+    }
+    elseif ($op == 'Test Transformation Rules') {
+=======
+    } elseif ($op == 'Test Transformation Rules') {
+>>>>>>> 6.x-0.4-dev
+
+      $patterns = $form_state['storage']['regex']['pattern'];
+      $replaces = $form_state['storage']['regex']['replace'];
+      $test_string = $form_state['values']['test_string'];
+      $form_state['storage']['test_regex_result'] = preg_replace($patterns, $replaces, $test_string);
+      $form_state['storage']['test_regex_test'] = $test_string;
+    }
+  }
+
+}
+
+/**
+ * Edit Field Form
+ *
+ * This form is meant to be called from a bulk loader form. The following should be set
+ * in the query section of the path:
+ *  - template_id=\d+: the template which the edited field is part of
+ *  - record_id=\d+: the priority or key in the template array of the record the field
+ *      is currently part of
+ *  - field_index=\d+: the key of the field in the fields array of the previously
+ *      specified record
+ *
+ * @param $form_state
+ *   Contains the values and storage for the form
+ * @return
+ *   A form array to be rendered by drupal_get_form
+ */
+function tripal_bulk_loader_edit_template_field_form(&$form_state = NULL) {
+  $form = array();
+<<<<<<< HEAD
+   $form['#cache'] = TRUE; // Make sure the form is cached.
+
+   // get template id from path
+   $template_id = ($_GET['template_id']) ? $_GET['template_id'] : $form_state['values']['template_id'];
+
+   // if there is no template supplied don't return rest of form
+   if (!$template_id) {
+     return $form;
+   }
+=======
+ 	$form['#cache'] = TRUE; // Make sure the form is cached.
+
+ 	// get template id from path
+ 	$template_id = ($_GET['template_id']) ? $_GET['template_id'] : $form_state['values']['template_id'];
+
+ 	// if there is no template supplied don't return rest of form
+ 	if (!$template_id) {
+ 	  return $form;
+ 	}
+>>>>>>> 6.x-0.4-dev
+
+  // Pre-set Variables needed for form proper------------------------------------------
+
+   // If this is the first load of the form (no form state) we need to initialize some variables
+   if (!$form_state['storage']['template']) {
+    $sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+    $template = db_fetch_object(db_query($sql, $template_id));
+    $form_state['storage']['template_array'] = unserialize($template->template_array);
+    $form_state['storage']['template'] = $template;
+
+    $form_state['storage']['record2priority'] = array();
+    foreach ($form_state['storage']['template_array'] as $priority => $record_array) {
+      if (!is_array($record_array)) {
+         continue;
+       }
+      $form_state['storage']['record2priority'][$record_array['record_id']] = $priority;
+    }
+
+    $form_state['storage']['referring URL'] = $_SERVER["HTTP_REFERER"];
+  }
+  else {
+    $template = $form_state['storage']['template'];
+  }
+
+  // get the field from the path
+  if (!($_GET['record_id']===NULL || $_GET['field_index']===NULL)) {
+    $priority = $_GET['record_id'];
+    $field_index = $_GET['field_index'];
+    $template_field = $form_state['storage']['template_array'][$priority]['fields'][$field_index];
+    $form_state['storage']['original_field'] = $template_field;
+    $form_state['storage']['original_field']['priority'] = $priority;
+    $form_state['storage']['original_field']['field_index'] = $field_index;
+  }
+
+  $field_type = ($form_state['values']['field_type'])? $form_state['values']['field_type'] : $template_field['type'];
+
+  // Tables and default table
+  $tables = tripal_core_get_chado_tables();
+  if ($form_state['values']) {
+    $table = $form_state['values']['chado_table'];
+<<<<<<< HEAD
+  }
+  else {
+    $table = $form_state['storage']['template_array'][$priority]['table'];
+  }
+=======
+  } else {
+    $table = $form_state['storage']['template_array'][$priority]['table'];
+  }
+>>>>>>> 6.x-0.4-dev
+
+
+  // Fields and foreign key mappings
+  $chado_fields = array();
+  $fk_options = array();
+  $fk_options['NULL'] = 'None';
+  $table_description = module_invoke_all('chado_' . $table . '_schema');
+  if ($field_type == 'foreign key') {
+    $foreign_field2table = array();
+    foreach ($table_description['foreign keys'] as $key_table => $key_array) {
+      foreach ($key_array['columns'] as $left_field => $right_field) {
+        $chado_fields[$left_field] = $left_field;
+        $foreign_field2table[$left_field] = $key_table;
+      }
+    }
+    reset($chado_fields);
+
+    // set default field
+    if (empty($chado_fields)) {
+      $field = NULL;
+    }
+    elseif ($chado_fields[$form_state['values']['chado_field']]) {
+      $field = $form_state['values']['chado_field'];
+    }
+    elseif ($template_field['field']) {
+      $field = $template_field['field'];
+    }
+    else {
+      $field = current($chado_fields);
+    }
+    //dpm($field, 'field');
+
+    // Foreign key options
+    $foreign_table = $foreign_field2table[$field];
+    if ($foreign_table) {
+      foreach ($form_state['storage']['record2priority'] as $record_name_ => $priority_ ) {
+        if (preg_match('/^' . $foreign_table . '$/', $form_state['storage']['template_array'][$priority_]['table'])) {
+          $fk_options[$record_name_] = $record_name_;
+        }
+      }
+    }
+  }
+  else {
+    foreach ($table_description['fields'] as $field_name => $field_array) {
+        $chado_fields[$field_name] = $field_name;
+    }
+  }
+
+//  dpm(array( 'tables' => $tables, 'default table' => $table, 'record name' => $record_name, 'priority' => $priority,
+//    'fields' => $chad_fields, 'default field' => $field, 'foreign field=>table' => $foreign_field2table,
+//    'table desc' => $table_description, 'foreign record options' => $fk_options, 'foreign table' => $foreign_table
+//    ), 'Variables');
+
+  // Start of Form Proper--------------------------------------------------------------
+
+  $form['template_name'] = array(
+    '#type' => 'item',
+    '#title' => 'Template',
+    '#value' => $template->name,
+  );
+
+  $form['template_id'] = array(
+    '#type' => 'hidden',
+    '#value' => $template_id,
+  );
+
+  $form['edit_fields'] = array(
+    '#type' => 'fieldset',
+    '#prefix' => '<div id="tripal_bulk_loader_template-edit_field">',
+    '#suffix' => '</div>',
+  );
+
+  $form['edit_fields']['field_type'] = array(
+    '#type' => 'radios',
+    '#title' => t('Type of Field'),
+    '#options' => array(
+      'table field' => t('Spreadsheet: Fields which maps to a Spreadsheet Column'),
+      'constant' => t('Constant: Field which remains Constant throughout the Spreadsheet'),
+      'foreign key' => t('Foreign Key: Fields which map to a record in another table'),
+    ),
+    '#required' => TRUE,
+    '#default_value' => $field_type,
+    '#ahah' => array(
+      'path' => 'admin/tripal/tripal_bulk_loader_template/edit_field_ahah',
+      'wrapper' => 'tripal_bulk_loader_template-edit_field',
+      'effect' => 'fade'
+    ),
+  );
+
+  // check template array for records then edit one more
+  if (!$form_state['storage']['record2priority']) {
+    $groups = array();
+  }
+  else {
+    $groups = array_flip($form_state['storage']['record2priority']);
+  }
+  $groups['NONE'] = 'Select a Record';
+  $groups['NEW'] = 'New Record';
+  $form['edit_fields']['field_group']  = array(
+    '#type' => 'select',
+    '#title' => 'Record',
+    '#description' => 'This is used to group a set of fields together allowing '
+      .'multiple records to be inserted into the same table per line of the spreadsheet',
+    '#options' => $groups,
+    '#default_value' => (preg_match('/(\d+|\w+)/', $form_state['values']['field_group'])) ? $form_state['values']['field_group'] : $priority,
+    '#ahah' => array(
+      'path' => 'admin/tripal/tripal_bulk_loader_template/edit_field_ahah',
+      'wrapper' => 'tripal_bulk_loader_template-edit_field',
+      'effect' => 'fade'
+    ),
+    '#required' => TRUE,
+  );
+
+  $form['edit_fields']['record_name'] = array(
+    '#type' => (preg_match('/NEW/', $form_state['values']['field_group'])) ? 'textfield' : 'hidden',
+    '#title' => 'Unique Record Name',
+    '#prefix' => '<div id="tripal_bulk_loader_template-edit_record">',
+    '#suffix' => '</div>',
+    '#default_value' => $form_state['values']['record_name'],
+  );
+
+  $form['edit_fields']['field_title'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Human-readable Title for Field'),
+    '#default_value' => ($form_state['values']['field_title']) ? $form_state['values']['field_title'] : $template_field['title'],
+  );
+
+  // Spreadsheet column
+  $form['edit_fields']['columns'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Spreadsheet Column'),
+    '#collapsible' => TRUE,
+    '#collapsed' => ($field_type == 'table field')? FALSE : TRUE,
+  );
+
+  $form['edit_fields']['columns']['sheet_name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Worksheet'),
+    '#description' => t('Specify the name of the worksheet.'),
+    '#size' => 5,
+    '#default_value' => ($form_state['values']['sheet_name'])? $form_state['values']['sheet_name'] : $template_field['spreadsheet sheet'],
+  );
+
+  $form['edit_fields']['columns']['column_number'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Column'),
+    '#description' => t('Specify the column in the spreadsheet that this field maps to where the first column is 1.'),
+    '#size' => 5,
+    '#default_value' => ($form_state['values']['column_number']) ? $form_state['values']['column_number'] : $template_field['spreadsheet column'],
+  );
+
+  $form['edit_fields']['columns']['column_exposed'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Allow Column to be set for each Bulk Loading Job'),
+    '#description' => t('Adds a textbox field to the Bulk Loader Page to allow users to set this value.'),
+    '#default_value' => ($form_state['values']['column_exposed']) ? $form_state['values']['column_exposed'] : $template_field['exposed'],
+  );
+
+  $form['edit_fields']['columns']['column_exposed_desc'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Description for exposed field on bulk loading job'),
+    '#description' => t('This description should tell the user what column should be entered here.'),
+    '#default_value' => ($form_state['values']['column_exposed_desc']) ? $form_state['values']['column_exposed_desc'] : $template_field['exposed_description'],
+  );
+
+  // Global Value
+  $form['edit_fields']['constant'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Constant'),
+    '#collapsible' => TRUE,
+    '#collapsed' => ($field_type == 'constant')? FALSE : TRUE,
+  );
+
+  $form['edit_fields']['constant']['constant_value'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Constant Value'),
+    '#description' => t('Specify the value you wish this field to have regardless of spreadsheet data.'),
+    '#default_value' => ($form_state['values']['constant_value']) ? $form_state['values']['constant_value'] : $template_field['constant value'],
+  );
+
+  $form['edit_fields']['constant']['constant_exposed'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Allow Constant to be set for each Bulk Loading Job'),
+    '#description' => t('Adds a textbox field to the Create Bulk Loader Form to allow users to set this value.'),
+    '#default_value' => ($form_state['values']['constant_exposed']) ? $form_state['values']['constant_exposed'] : $template_field['exposed'],
+  );
+
+  $form['edit_fields']['constant']['constant_validate'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Ensure value is in table'),
+    '#description' => t('Checks the database when a bulk loading job is created to ensure the value entered already exists in the database.'),
+    '#default_value' => ($form_state['values']['constant_validate']) ? $form_state['values']['constant_validate'] : $template_field['exposed_validate'],
+  );
+
+  // Foreign Key
+  $form['edit_fields']['foreign_key'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Foreign Key',
+    '#collapsible' => TRUE,
+    '#collapsed' => ($field_type == 'foreign key')? FALSE : TRUE,
+  );
+
+  $form['edit_fields']['foreign_key']['foreign_record'] = array(
+    '#type' => 'select',
+    '#title' => 'Record to refer to',
+    '#descripion' => 'Select the record that this foreign key shouold refer to. The record needs to already exist and be of the correct table.',
+    '#options' => $fk_options,
+  );
+
+  // Chado Field
+  $form['edit_fields']['chado'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Chado Field/Column Details'),
+    '#description' => t('Specify the Table/Field in chado that this field maps to.'),
+  );
+
+  $form['edit_fields']['chado']['chado_table'] = array(
+    '#type' => 'select',
+    '#title' => t('Chado Table'),
+    '#options' => $tables,
+    '#default_value' => $table,
+    '#ahah' => array(
+      'path' => 'admin/tripal/tripal_bulk_loader_template/edit_field_ahah',
+      'wrapper' => 'tripal_bulk_loader_template-edit_field',
+      'effect' => 'fade'
+      ),
+  );
+
+  $form['edit_fields']['chado']['chado_field'] = array(
+    '#type' => 'select',
+    '#title' => t('Chado Field/Column'),
+    '#options' => $chado_fields,
+    '#default_value' => ($form_state['values']['chado_field']) ? $form_state['values']['chado_field'] : $template_field['field'],
+    '#ahah' => array(
+      'path' => 'admin/tripal/tripal_bulk_loader_template/edit_field_ahah',
+      'wrapper' => 'tripal_bulk_loader_template-edit_field',
+      'effect' => 'fade'
+    ),
+  );
+
+  $form['edit_fields']['additional'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Additional Options',
+  );
+
+  $form['edit_fields']['additional']['required'] = array(
+    '#type' => 'checkbox',
+    '#title' => 'Make this file required',
+    '#default_value' => $template_field['required'],
+  );
+
+  $form['edit_fields']['additional']['regex_transform'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Transform Spreadsheet Value Rules',
+    '#collapsible' => TRUE,
+    '#collapsed' => (!$template_field['regex']['pattern']) ? TRUE : FALSE,
+  );
+
+  $transformation_msg = '<p>A transformation rule allows you to transform the original value '
+      .'(usually from a user submitted spreadsheet) into the form you would like it stored '
+      .'in the chado database. Each rule consists of a match pattern (a php regular expression '
+      .'which determines which replacement patterns are applied and captures regions of the '
+      .'original value) and a replacement pattern (a string which may contain capture references '
+      .'that describes what the new value should be). Each rule is applied to the result of the '
+      .'previous rule.<p>';
+  $form['edit_fields']['additional']['regex_transform']['regex_description'] = array(
+    '#type' => 'item',
+    '#value' => $transformation_msg,
+  );
+
+  $form['edit_fields']['additional']['regex_transform']['regex-data'] = array(
+    '#tree' => TRUE,
+  );
+  foreach ($template_field['regex']['pattern'] as $index => $pattern) {
+    $data_element = array(
+      'pattern' => array(
+        '#type' => 'item',
+        '#value' => $pattern,
+      ),
+      'replace' => array(
+        '#type' => 'item',
+        '#value' => $template_field['regex']['replace'][$index],
+      ),
+      'old_index' => array(
+        '#type' => 'hidden',
+        '#value' => $index,
+      ),
+      'new_index' => array(
+        '#type' => 'select',
+        '#options' => range(0, sizeof($template_field['regex']['pattern'])-1),
+        '#default_value' => $index,
+      ),
+      'id' => array(
+        '#type' => 'hidden',
+        '#value' => $index,
+      ),
+      'submit-delete' => array(
+        '#type' => 'submit',
+        '#value' => 'Delete Transformation',
+        '#name' => $index,
+      ),
+    );
+    $form['edit_fields']['additional']['regex_transform']['regex-data'][$index] = $data_element;
+  }
+
+  $form['edit_fields']['additional']['regex_transform']['submit-reorder_regex'] = array(
+    '#type' => 'submit',
+    '#value' => 'Save Transformation Rule Order'
+  );
+
+  $form['edit_fields']['additional']['regex_transform']['new_regex'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Add a new Transformation Rule',
+  );
+
+  $form['edit_fields']['additional']['regex_transform']['new_regex']['pattern'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Match Pattern',
+    '#description' => 'You can use standard <b>php regular expressions</b> in this field to specify a '
+      .'pattern. Only if this pattern matches the value in the spreadsheet does the replacement '
+      .'pattern get applied to the value. To capture a section of your value for use in the '
+      .'replacement patten surround with round brackets. For example, <i>GI:(\d+)</i> will match '
+      .' NCBI gi numbers and will capture the numerical digits for use in the replacement pattern. '
+      .' To match and capture any value use <i>.*</i>',
+  );
+
+  $form['edit_fields']['additional']['regex_transform']['new_regex']['replace'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Replacement Pattern',
+    '#description' => '<p>This pattern should contain the text you want to replace the match pattern '
+    .'mentioned above. It can include references of the form <b>\n</b> where n is the number of the '
+    .'capture in the match pattern. For example, \1 will be replaced with the text matched in your '
+    .'first set of round brackets.</p>',
+  );
+
+  if ($field_type == 'table field') {
+    $tab = '&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp';
+    $form['edit_fields']['additional']['regex_transform']['new_regex']['replace']['#description'] .= '<p>'
+      .'The following references are also available for spreadsheet fields: <b><#column:<i>number</i>#></b>. '
+      .'This allows you to substitute other spreadsheet values into the current field. For example, '
+      .'if you had the following line:<br>'
+      . $tab . 'SNP' . $tab . '15-Jan-2011' . $tab . '1' . $tab . '54' . $tab . 'Contig34355'
+      .'<br> and your current field is for column #1 and you\'re inserting into the chado field '
+      .'feature.uniquename then you might want to add in the data to ensure your uniquename is '
+      .'unique. The Match Pattern is (.*) to select all the first column and the Replacement '
+      .'Pattern could be \1_<#column:2#> which would insert SNP_15-Jan-2011 into the database.</p>';
+  }
+
+  $form['edit_fields']['additional']['regex_transform']['new_regex']['submit-add_transform'] = array(
+    '#type' => 'submit',
+    '#value' => 'Add Transformation',
+  );
+
+  $form['edit_fields']['additional']['regex_transform']['test_regex'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Test Transformation Rules',
+  );
+
+  $form['edit_fields']['additional']['regex_transform']['test_regex']['test_string'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Test Value',
+    '#description' => 'This should be a value that you expect the above transformation rules '
+      .'to be applied to.',
+    '#default_value' => $form_state['storage']['test_regex_test'],
+  );
+
+  $form['edit_fields']['additional']['regex_transform']['test_regex']['test_result'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Test Result',
+    '#description' => 'This is the value that would be saved to the database after the above transformation '
+      .'riles were applied to the Test Value.',
+    '#default_value' => $form_state['storage']['test_regex_result'],
+  );
+
+  $form['edit_fields']['additional']['regex_transform']['test_regex']['submit-test'] = array(
+    '#type' => 'submit',
+    '#value' => 'Test Transformation Rules'
+  );
+
+  $form['edit_fields']['submit-edit_field'] = array(
+      '#type' => 'submit',
+      '#value' => 'Edit Field'
+  );
+
+  $form['edit_fields']['submit-cancel'] = array(
+      '#type' => 'submit',
+      '#value' => 'Cancel'
+  );
+
+  return $form;
+}
+
+/**
+ * Edit Field Form Submit
+ *
+ * @param $form
+ *   The form that was submitted
+ * @param $form_state
+ *   The values and storage for the form
+ */
+function tripal_bulk_loader_edit_template_field_form_submit($form, &$form_state) {
+
+  $op = $form_state['values'][ $form_state['clicked_button']['#name'] ];
+  //dpm($op, 'Operation Submitted');
+
+  //Clear Test
+  $form_state['storage']['test_regex_result'] = NULL;
+  $form_state['storage']['test_regex_test'] = NULL;
+
+  if (!$form_state['ahah_submission']) {
+    if ($op ==  'Edit Field') {
+
+      // If new record
+      if (preg_match('/NEW/', $form_state['values']['field_group'])) {
+        // add new record
+        $record_name = $form_state['values']['record_name'];
+        $priority = sizeof($form_state['storage']['template_array']) + 1;
+        $old_priority = $form_state['storage']['original_field']['priority'];
+        $field_index = $form_state['storage']['original_field']['field_index'];
+        $form_state['storage']['record2priority'][$record_name] = $priority;
+        $form_state['storage']['template_array'][$priority]['table'] = $form_state['values']['chado_table'];
+        $form_state['storage']['template_array'][$priority]['record_id'] = $record_name;
+
+<<<<<<< HEAD
+      }
+      else {
+=======
+      } else {
+>>>>>>> 6.x-0.4-dev
+        $priority = $form_state['values']['field_group'];
+        $old_priority = $form_state['storage']['original_field']['priority'];
+        $field_index = $form_state['storage']['original_field']['field_index'];
+        $record_name = $form_state['storage']['record2priority'][$priority];
+      }
+
+      $field = $form_state['storage']['original_field'];
+      if ($form_state['values']['field_type'] == 'table field') {
+          $field['type'] = 'table field';
+          $field['title'] = $form_state['values']['field_title'];
+          $field['field'] = $form_state['values']['chado_field'];
+          $field['required'] = $form_state['values']['required'];
+          //$field['allowed values'] = empty by default;
+          $field['spreadsheet sheet'] = $form_state['values']['sheet_name'];
+          $field['spreadsheet column'] = $form_state['values']['column_number'];
+          $field['exposed'] = $form_state['values']['column_exposed'];
+          $field['exposed_description'] = $form_state['values']['column_exposed_desc'];
+      }
+      elseif ($form_state['values']['field_type'] == 'constant') {
+          $field['type'] = 'constant';
+          $field['title'] = $form_state['values']['field_title'];
+          $field['field'] = $form_state['values']['chado_field'];
+          $field['required'] = $form_state['values']['required'];
+          //$field['allowed values'] = empty by default;
+          $field['constant value'] = $form_state['values']['constant_value'];
+          $field['exposed_validate'] = $form_state['values']['constant_validate'];
+          $field['exposed'] = $form_state['values']['constant_exposed'];
+<<<<<<< HEAD
+      }
+      elseif ($form_state['values']['field_type'] == 'foreign key') {
+=======
+      } elseif ($form_state['values']['field_type'] == 'foreign key') {
+>>>>>>> 6.x-0.4-dev
+          $field['type'] = 'foreign key';
+          $field['title'] = $form_state['values']['field_title'];
+          $field['field'] = $form_state['values']['chado_field'];
+          $field['foreign key'] = $form_state['values']['foreign_record'];
+          $field['required'] = $form_state['values']['required'];
+      }
+
+      // Deal with any additional options
+
+      // if the record has changed...
+      $form_state['storage']['template_array'][$priority]['table'] = $form_state['values']['chado_table'];
+      if ($old_priority != $priority) {
+        $form_state['storage']['template_array'][$priority]['fields'][] = $field;
+        unset($form_state['storage']['template_array'][$old_priority]['fields'][$field_index]);
+
+        // if there are no fields left delete the old record
+        if (!$form_state['storage']['template_array'][$old_priority]['fields']) {
+          unset($form_state['storage']['template_array'][$old_priority]);
+        }
+      }
+      else {
+        $form_state['storage']['template_array'][$priority]['fields'][$field_index] = $field;
+      }
+
+      // Save Template
+      $form_state['storage']['template']->template_array = serialize($form_state['storage']['template_array']);
+      $success = drupal_write_record('tripal_bulk_loader_template', $form_state['storage']['template'], array('template_id'));
+
+      if ($success) {
+        drupal_set_message('Successfully Updated Field');
+        drupal_set_message('Template Saved.');
+
+        $path = explode('?', $form_state['storage']['referring URL']);
+        parse_str($path[1], $query);
+        $query['template_id'] = $form_state['storage']['template']->template_id;
+        drupal_goto($path[0], $query);
+<<<<<<< HEAD
+      }
+      else {
+=======
+      } else {
+>>>>>>> 6.x-0.4-dev
+        drupal_set_message('Unable to Save Template!', 'error');
+        watchdog('T_bulk_loader',
+          'Unable to save bulk loader template: %template',
+          array('%template' => print_r($form_state['storage']['template'], TRUE)),
+          WATCHDOG_ERROR
+        );
+      }
+
+<<<<<<< HEAD
+    }
+    elseif ($op ==  'Cancel') {
+
+        $path = explode('?', $form_state['storage']['referring URL']);
+=======
+    } elseif ($op ==  'Cancel') {
+
+        $path = explode('?',$form_state['storage']['referring URL']);
+>>>>>>> 6.x-0.4-dev
+        parse_str($path[1], $query);
+        $query['template_id'] = $form_state['storage']['template']->template_id;
+        drupal_goto($path[0], $query);
+
+    }
+    elseif ($op == 'Add Transformation') {
+
+      // Add transformation rule to original field
+      $form_state['storage']['original_field']['regex']['pattern'][] = '/' . $form_state['values']['pattern'] . '/';
+      $form_state['storage']['original_field']['regex']['replace'][] = $form_state['values']['replace'];
+
+      // Add original field back into template
+      $priority = $form_state['storage']['original_field']['priority'];
+      $field_index = $form_state['storage']['original_field']['field_index'];
+      $form_state['storage']['template_array'][$priority]['fields'][$field_index] = $form_state['storage']['original_field'];
+
+      // Save Template
+      $form_state['storage']['template']->template_array = serialize($form_state['storage']['template_array']);
+      $success = drupal_write_record('tripal_bulk_loader_template', $form_state['storage']['template'], array('template_id'));
+
+      if ($success) {
+        drupal_set_message('Successfully Added Transformation Rule');
+        drupal_set_message('Template Saved.');
+<<<<<<< HEAD
+      }
+      else {
+=======
+      } else {
+>>>>>>> 6.x-0.4-dev
+        drupal_set_message('Unable to Save Template!', 'error');
+        watchdog('T_bulk_loader',
+          'Unable to save bulk loader template: %template',
+          array('%template' => print_r($form_state['storage']['template'], TRUE)),
+          WATCHDOG_ERROR
+        );
+      }
+<<<<<<< HEAD
+    }
+    elseif ($op == 'Save Transformation Rule Order') {
+=======
+    } elseif ($op == 'Save Transformation Rule Order') {
+>>>>>>> 6.x-0.4-dev
+
+      // Generate new regex array
+      $new_regex = array();
+      $old_regex = $form_state['storage']['original_field']['regex'];
+      foreach ($form_state['values']['regex-data'] as $key => $element) {
+        $new_regex['pattern'][ $element['new_index'] ] = $old_regex['pattern'][ $element['old_index'] ];
+        $new_regex['replace'][ $element['new_index'] ] = $old_regex['replace'][ $element['old_index'] ];
+      }
+
+      // sort new regex arrays
+      asort($new_regex['pattern']);
+      asort($new_regex['replace']);
+
+      // Add back to original field
+      $form_state['storage']['original_field']['regex'] = $new_regex;
+      $priority = $form_state['storage']['original_field']['priority'];
+      $field_index = $form_state['storage']['original_field']['field_index'];
+      $form_state['storage']['template_array'][$priority]['fields'][$field_index] = $form_state['storage']['original_field'];
+
+      // Save Template
+      $form_state['storage']['template']->template_array = serialize($form_state['storage']['template_array']);
+      $success = drupal_write_record('tripal_bulk_loader_template', $form_state['storage']['template'], array('template_id'));
+
+      if ($success) {
+        drupal_set_message('Successfully Reordered Transformation Rules');
+        drupal_set_message('Template Saved.');
+<<<<<<< HEAD
+      }
+      else {
+=======
+      } else {
+>>>>>>> 6.x-0.4-dev
+        drupal_set_message('Unable to Save Template!', 'error');
+        watchdog('T_bulk_loader',
+          'Unable to save bulk loader template: %template',
+          array('%template' => print_r($form_state['storage']['template'], TRUE)),
+          WATCHDOG_ERROR
+        );
+      }
+<<<<<<< HEAD
+    }
+    elseif ($op == 'Delete Transformation') {
+=======
+    } elseif ($op == 'Delete Transformation') {
+>>>>>>> 6.x-0.4-dev
+
+      // Unset regex rule
+      $index = $form_state['clicked_button']['#name'];
+      unset($form_state['storage']['original_field']['regex']['pattern'][$index]);
+      unset($form_state['storage']['original_field']['regex']['replace'][$index]);
+
+      $priority = $form_state['storage']['original_field']['priority'];
+      $field_index = $form_state['storage']['original_field']['field_index'];
+      $form_state['storage']['template_array'][$priority]['fields'][$field_index] = $form_state['storage']['original_field'];
+
+      // Save Template
+      $form_state['storage']['template']->template_array = serialize($form_state['storage']['template_array']);
+      $success = drupal_write_record('tripal_bulk_loader_template', $form_state['storage']['template'], array('template_id'));
+
+      if ($success) {
+        drupal_set_message('Successfully Reordered Transformation Rules');
+        drupal_set_message('Template Saved.');
+<<<<<<< HEAD
+      }
+      else {
+=======
+      } else {
+>>>>>>> 6.x-0.4-dev
+        drupal_set_message('Unable to Save Template!', 'error');
+        watchdog('T_bulk_loader',
+          'Unable to save bulk loader template: %template',
+          array('%template' => print_r($form_state['storage']['template'], TRUE)),
+          WATCHDOG_ERROR
+        );
+      }
+
+<<<<<<< HEAD
+    }
+    elseif ($op == 'Test Transformation Rules') {
+=======
+    } elseif ($op == 'Test Transformation Rules') {
+>>>>>>> 6.x-0.4-dev
+
+      $patterns = $form_state['storage']['original_field']['regex']['pattern'];
+      $replaces = $form_state['storage']['original_field']['regex']['replace'];
+      $test_string = $form_state['values']['test_string'];
+      $form_state['storage']['test_regex_result'] = preg_replace($patterns, $replaces, $test_string);
+      $form_state['storage']['test_regex_test'] = $test_string;
+    }
+  }
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+// AHAH Callbacks
+//////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * AHAH Function: Replace $form['add_fields'] in tripal_bulk_loader_add_template_field_form
+ *
+ * @return
+ *  JSON Data printed to the screen
+ */
+function tripal_bulk_loader_add_field_ahah() {
+
+  $form_state = array('storage' => NULL, 'submitted' => FALSE);
+  $form_build_id = $_POST['form_build_id'];
+  $form = form_get_cache($form_build_id, $form_state);
+  $args = $form['#parameters'];
+  $form_id = array_shift($args);
+  $form_state['post'] = $form['#post'] = $_POST;
+
+  // Enable the submit/validate handlers to determine whether AHAH-submittted.
+  $form_state['ahah_submission'] = TRUE;
+
+  $form['#programmed'] = $form['#redirect'] = FALSE;
+  drupal_process_form($form_id, $form, $form_state);
+  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
+
+  $form_element = $form['add_fields'];
+  // Remove the wrapper so we don't double it up.
+  //unset($form_element['#prefix'], $form_element['#suffix']);
+
+  $output = theme('status_messages');
+  $output .= drupal_render($form_element);
+
+  // Final rendering callback.
+  print drupal_json(array('status' => TRUE, 'data' => $output));
+  exit();
+
+}
+
+/**
+ * AHAH Function: Replace $form['edit_fields'] in tripal_bulk_loader_edit_template_field_form
+ *
+ * @return
+ *  JSON Data printed to the screen
+ */
+function tripal_bulk_loader_edit_field_ahah() {
+
+  $form_state = array('storage' => NULL, 'submitted' => FALSE);
+  $form_build_id = $_POST['form_build_id'];
+  $form = form_get_cache($form_build_id, $form_state);
+  $args = $form['#parameters'];
+  $form_id = array_shift($args);
+  $form_state['post'] = $form['#post'] = $_POST;
+
+  // Enable the submit/validate handlers to determine whether AHAH-submittted.
+  $form_state['ahah_submission'] = TRUE;
+
+  $form['#programmed'] = $form['#redirect'] = FALSE;
+  drupal_process_form($form_id, $form, $form_state);
+  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
+
+  $form_element = $form['edit_fields'];
+  // Remove the wrapper so we don't double it up.
+  unset($form_element['#prefix'], $form_element['#suffix']);
+
+  $output = theme('status_messages');
+  $output .= drupal_render($form_element);
+
+  // Final rendering callback.
+  print drupal_json(array('status' => TRUE, 'data' => $output));
+  exit();
+
+<<<<<<< HEAD
+}
+=======
+}
+>>>>>>> 6.x-0.4-dev

+ 10 - 3
tripal_bulk_loader/tripal_bulk_loader.loader.inc

@@ -420,11 +420,18 @@ function process_data_array_for_line($priority, &$data, &$default_data, $field2c
 
   if (!preg_match('/select/', $table_data['mode'])) {
     //watchdog('T_bulk_loader',$header.': Inserting:'.print_r($values, TRUE), array(), WATCHDOG_NOTICE);
-    $options = array('statement_name' => $priority);
-    if ($line_num == 1 && $group_index == 1) {
-      $options['prepare'] = TRUE;
+    if (variable_get('tripal_bulk_loader_prepare',TRUE)) {
+      $options = array('statement_name' => $priority);
+      if ($line_num == 1 && $group_index == 1) {
+        $options['prepare'] = TRUE;
+      }
+    }
+    else {
+      $options = array();
     }
+
     $record = tripal_core_chado_insert($table, $values, $options);
+
     if (!$record) {
       $msg = 'Line ' . $line_num . ' ' . $table_data['record_id'] . ' (' . $table_data['mode'] . ') Unable to insert record into ' . $table . ' where values:' . print_r($values, TRUE);
       watchdog('T_bulk_loader', $msg, array(), WATCHDOG_ERROR);

+ 733 - 0
tripal_bulk_loader/tripal_bulk_loader.loader.inc.orig

@@ -0,0 +1,733 @@
+<?php
+
+/**
+ * @file
+ * @todo Add file header description
+ */
+
+/**
+ * Add Loader Job Form
+ *
+ * This form is meant to be included on the node page to allow users to submit/re-submit
+ * loading jobs
+ */
+function tripal_bulk_loader_add_loader_job_form($form_state, $node) {
+  $form = array();
+
+  $form['nid'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->nid,
+  );
+
+  $form['file'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->file
+  );
+
+  $form['job_id'] = array(
+    '#type' => 'hidden',
+    '#value' => $node->job_id,
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => ($node->job_id) ? 'Re-Submit Job' : 'Submit Job',
+  );
+
+  $form['submit-cancel'] = array(
+    '#type' => ($node->job_id)? 'submit' : 'hidden',
+    '#value' => 'Cancel Job',
+  );
+
+  $form['submit-revert'] = array(
+    '#type' => ($node->job_id) ? 'submit' : 'hidden',
+    '#value' => 'Revert',
+  );
+
+  return $form;
+}
+
+/**
+ * Add Loader Job Form (Submit)
+ */
+function tripal_bulk_loader_add_loader_job_form_submit($form, $form_state) {
+  global $user;
+
+  if (preg_match('/Submit Job/', $form_state['values']['op'])) {
+    //Submit Tripal Job
+<<<<<<< HEAD
+    $job_args[1] = $form_state['values']['nid'];
+    if (is_readable($form_state['values']['file'])) {
+      $fname = basename($form_state['values']['file']);
+      $job_id = tripal_add_job("Bulk Loading Job: $fname", 'tripal_bulk_loader', 'tripal_bulk_loader_load_data', $job_args, $user->uid);
+
+      // add job_id to bulk_loader node
+      $success = db_query("UPDATE {tripal_bulk_loader} SET job_id=%d WHERE nid=%d", $job_id, $form_state['values']['nid']);
+
+      // change status
+      db_query("UPDATE {tripal_bulk_loader} SET job_status='%s' WHERE nid=%d", 'Submitted to Queue', $form_state['values']['nid']);
+    }
+    else {
+      drupal_set_message(t("Can not open %file. Job not scheduled.", array('%file' => $form_state['values']['file'])));
+    }
+  }
+  elseif (preg_match('/Re-Submit Job/', $form_state['values']['op'])) {
+=======
+		$job_args[1] = $form_state['values']['nid'];
+		if (is_readable($form_state['values']['file'])) {
+			$fname = basename($form_state['values']['file']);
+			$job_id = tripal_add_job("Bulk Loading Job: $fname",'tripal_bulk_loader', 'tripal_bulk_loader_load_data', $job_args, $user->uid);
+
+			// add job_id to bulk_loader node
+      $success = db_query("UPDATE {tripal_bulk_loader} SET job_id=%d WHERE nid=%d", $job_id, $form_state['values']['nid']);
+
+      // change status
+      db_query("UPDATE tripal_bulk_loader SET job_status='%s' WHERE nid=%d",'Submitted to Queue', $form_state['values']['nid']);
+		} else {
+			drupal_set_message("Can not open ".$form_state['values']['file'].". Job not scheduled.");
+		}
+  } elseif (preg_match('/Re-Submit Job/', $form_state['values']['op'])) {
+>>>>>>> 6.x-0.4-dev
+    tripal_jobs_rerun($form_state['values']['job_id']);
+    db_query("UPDATE {tripal_bulk_loader} SET job_status='%s' WHERE nid=%d", 'Submitted to Queue', $form_state['values']['nid']);
+  }
+  elseif (preg_match('/Cancel Job/', $form_state['values']['op'])) {
+    db_query("UPDATE {tripal_bulk_loader} SET job_status='%s' WHERE nid=%d", 'Job Cancelled', $form_state['values']['nid']);
+    tripal_jobs_cancel($form_state['values']['job_id']);
+<<<<<<< HEAD
+  }
+  elseif (preg_match('/Revert/', $form_state['values']['op'])) {
+=======
+  } elseif (preg_match('/Revert/', $form_state['values']['op'])) {
+>>>>>>> 6.x-0.4-dev
+
+    // Remove the records from the database that were already inserted
+    $resource = db_query('SELECT * FROM {tripal_bulk_loader_inserted} WHERE nid=%d ORDER BY tripal_bulk_loader_inserted_id DESC', $form_state['values']['nid']);
+    while ($r = db_fetch_object($resource)) {
+      $ids = preg_split('/,/', $r->ids_inserted);
+      db_query('DELETE FROM %s WHERE %s IN (%s)', $r->table_inserted_into, $r->table_primary_key, $r->ids_inserted);
+      $result = db_fetch_object(db_query('SELECT true as present FROM %s WHERE %s IN (%s)', $r->table_inserted_into, $r->table_primary_key, $r->ids_inserted));
+      if (!$result->present) {
+        drupal_set_message(t('Successfully Removed data Inserted into the %tableto table.', array('%tableto' => $r->table_inserted_into)));
+        db_query('DELETE FROM {tripal_bulk_loader_inserted} WHERE tripal_bulk_loader_inserted_id=%d', $r->tripal_bulk_loader_inserted_id);
+      }
+      else {
+        drupal_set_message(t('Unable to remove data Inserted into the %tableto table!', array('%tableto' => $r->table_inserted_into)), 'error');
+      }
+    }
+
+    // reset status
+    db_query("UPDATE {tripal_bulk_loader} SET job_status='%s' WHERE nid=%d", 'Reverted -Data Deleted', $form_state['values']['nid']);
+  }
+
+}
+
+/**
+ * Tripal Bulk Loader
+ *
+ * This is the function that's run by tripal_launch_jobs to bulk load chado data.
+ *
+ * @param $nid
+ *   The Node ID of the bulk loading job node to be loaded. All other needed data is expected to be
+ *   in the node (ie: template ID and file)
+ *
+ * Note: Instead of returning a value this function updates the tripal_bulk_loader.status.
+ *   Errors are thrown through watchdog and can be viewed at admin/reports/dblog.
+ */
+function tripal_bulk_loader_load_data($nid) {
+
+  // ensure no timeout
+  set_time_limit(0);
+
+  // set the status of the job (in the node not the tripal jobs)
+  db_query("UPDATE {tripal_bulk_loader} SET job_status='%s' WHERE nid=%d", 'Loading...', $nid);
+
+
+<<<<<<< HEAD
+=======
+
+>>>>>>> 6.x-0.4-dev
+  $node = node_load($nid);
+  print "Template: " . $node->template->name . " (" . $node->template_id . ")\n";
+
+  $total_lines = trim(`wc --lines < $node->file`);
+<<<<<<< HEAD
+  print "File: " . $node->file . " (" . $total_lines . " lines)\n";
+=======
+  print "File: ".$node->file." (".$total_lines." lines)\n";
+>>>>>>> 6.x-0.4-dev
+
+  // Prep Work ==================================================================================
+  $loaded_without_errors = TRUE;
+
+  // Generate default values array
+  $default_data = array();
+  $field2column = array();
+  $record2priority = array();
+
+  foreach ($node->template->template_array as $priority => $record_array) {
+    if (!is_array($record_array)) {
+      continue;
+    }
+
+    //watchdog('T_bulk_loader','1)'.$record_array['record_id']." => \n<pre>".print_r($record_array,TRUE).'</pre>', array(), WATCHDOG_NOTICE);
+
+    foreach ($record_array['fields'] as $field_index => $field_array) {
+
+      $default_data[$priority]['table'] = $record_array['table'];
+      $default_data[$priority]['mode'] = ($record_array['mode']) ? $record_array['mode'] : 'insert_unique';
+      $default_data[$priority]['record_id'] = $record_array['record_id'];
+      $record2priority[$record_array['record_id']] = $priority;
+      $default_data[$priority]['required'][$field_array['field']] = $field_array['required'];
+
+      $one = $default_data[$priority];
+      if (isset($field_array['regex'])) {
+        $default_data[$priority]['regex_transform'][$field_array['field']] = $field_array['regex'];
+      }
+
+      $two = $default_data[$priority];
+
+      if (preg_match('/table field/', $field_array['type'])) {
+        $default_data[$priority]['values_array'][$field_array['field']] = '';
+        $default_data[$priority]['need_further_processing'] = TRUE;
+        $field2column[$priority][$field_array['field']] = $field_array['spreadsheet column'];
+
+<<<<<<< HEAD
+      }
+      elseif (preg_match('/constant/', $field_array['type'])) {
+        $default_data[$priority]['values_array'][$field_array['field']] = $field_array['constant value'];
+
+      }
+      elseif (preg_match('/foreign key/', $field_array['type'])) {
+=======
+      } elseif (preg_match('/constant/', $field_array['type'])) {
+        $default_data[$priority]['values_array'][$field_array['field']] = $field_array['constant value'];
+
+      } elseif (preg_match('/foreign key/', $field_array['type'])) {
+>>>>>>> 6.x-0.4-dev
+        $default_data[$priority]['values_array'][$field_array['field']] = array();
+        $default_data[$priority]['values_array'][$field_array['field']]['foreign record'] = $field_array['foreign key'];
+        $default_data[$priority]['need_further_processing'] = TRUE;
+
+<<<<<<< HEAD
+      }
+      else {
+        print 'WARNING: Unsupported type: ' . $field_array['type'] . ' for ' . $table . '.' . $field_array['field'] . "!\n";
+=======
+      } else {
+        print 'WARNING: Unsupported type: '. $field_array['type'] . ' for ' . $table . '.' . $field_array['field']."!\n";
+>>>>>>> 6.x-0.4-dev
+      }
+
+      $three = $default_data[$priority];
+      //watchdog('T_bulk_loader','A)'.$field_index.':<pre>Field Array =>'.print_r($field_array,TRUE)."Initial => \n".print_r($one, TRUE)."\nAfter Regex =>".print_r($two, TRUE)."Final =>\n".print_r($three,TRUE).'</pre>', array(), WATCHDOG_NOTICE);
+
+    } // end of foreach field
+    //watchdog('T_bulk_loader','2)'.$record_array['record_id'].':<pre>'.print_r($default_data[$priority], TRUE).'</pre>', array(), WATCHDOG_NOTICE);
+  } //end of foreach record
+
+  ///////////////////////////////////////////////
+  // For each set of constants
+  ///////////////////////////////////////////////
+  $original_default_data = $default_data;
+  $group_index = 0;
+  $total_num_groups = sizeof($node->constants);
+  foreach ($node->constants as $group_id => $set) {
+    // revert default data array for next set of constants
+    $default_data = $original_default_data;
+    $group_index++;
+
+    // Add constants
+    if (!empty($set)) {
+      print "Constants:\n";
+      foreach ($set as $priority => $record) {
+        foreach ($record as $field_id => $field) {
+
+<<<<<<< HEAD
+          print "\t- " . $field['chado_table'] . '.' . $field['chado_field'] . ' = ' . $field['value'] . "\n";
+=======
+          print "\t- ".$field['chado_table'].'.'.$field['chado_field'].' = '.$field['value']."\n";
+>>>>>>> 6.x-0.4-dev
+
+          if ($default_data[$priority]['table'] == $field['chado_table']) {
+            if (isset($default_data[$priority]['values_array'][$field['chado_field']])) {
+              if (isset($field2column[$priority][$field['chado_field']])) {
+                $field2column[$priority][$field['chado_field']] = $field['value'];
+              }
+              else {
+                $default_data[$priority]['values_array'][$field['chado_field']] = $field['value'];
+              }
+            }
+            else {
+              print "ERROR: Template has changed after constants were assigned!\n";
+              watchdog('T_bulk_loader', 'Template has changed after constants were assigned', array(), WATCHDOG_NOTICE);
+              exit(1);
+            }
+          }
+          else {
+            print "ERROR: Template has changed after constants were assigned!\n";
+            watchdog('T_bulk_loader', 'Template has changed after constants were assigned', array(), WATCHDOG_NOTICE);
+            exit(1);
+          }
+        }
+      }
+    }
+
+    //print "Default Data:".print_r($default_data,TRUE)."\n";
+    //watchdog('T_bulk_loader','Default Data:<pre>'.print_r($default_data, TRUE).'</pre>', array(), WATCHDOG_NOTICE);
+
+    //print "\nDefault Values Array: ".print_r($default_data, TRUE)."\n";
+    //print "\nField to Column Mapping: ".print_r($field2column, TRUE)."\n";
+
+    // Parse File adding records as we go ========================================================
+    $file_handle = fopen($node->file, 'r');
+    if (preg_match('/(t|true|1)/', $node->file_has_header)) {
+      fgets($file_handle, 4096);
+    }
+    $num_records = 0;
+    $num_lines = 0;
+    $num_errors = 0;
+    $interval = intval($total_lines * 0.10);
+    if ($interval == 0) {
+       $interval = 1;
+     }
+    while (!feof($file_handle)) {
+
+      // Clear variables
+      // Was added to fix memory leak
+      unset($line);                     unset($raw_line);
+      unset($data);                     unset($data_keys);
+      unset($priority);                 unset($sql);
+      unset($result);
+
+      $raw_line = fgets($file_handle, 4096);
+      $raw_line = trim($raw_line);
+      if (empty($raw_line)) {
+        continue;
+      } // skips blank lines
+      $line = explode("\t", $raw_line);
+      $num_lines++;
+
+      // update the job status every 10% of lines processed for the current group
+      if ($node->job_id and $num_lines % $interval == 0) {
+        // percentage of lines processed for the current group
+        $group_progress = round(($num_lines/$total_lines)*100);
+
+        // percentage of lines processed for all groups
+        // <previous group index> * 100 + <current group progress>
+        // --------------------------------------------------------
+        //               <total number of groups>
+        // For example, if you were in the third group of 3 constant sets
+        // and had a group percentage of 50% then the job progress would be
+        // (2*100 + 50%) / 3 = 250%/3 = 83%
+        $job_progress = round(((($group_index-1)*100)+$group_progress)/$total_num_groups);
+
+        /**
+          print "\nProgress Update:\n"
+            ."\t- ".$num_lines." lines have been processed for the current constant set.\n"
+            ."\t- ".$group_progress."% of the lines in the file have been processed for the current constant set.\n"
+            ."\t- ".$job_progress."% of the current job has been completed.\n";
+        */
+
+<<<<<<< HEAD
+        tripal_job_set_progress($node->job_id, $job_progress);
+=======
+        tripal_job_set_progress($node->job_id,$job_progress);
+>>>>>>> 6.x-0.4-dev
+      }
+
+      $data = $default_data;
+
+      $data_keys = array_keys($data);
+      foreach ($data_keys as $priority) {
+        $status = process_data_array_for_line($priority, $data, $default_data, $field2column, $record2priority, $line, $nid, $num_lines, $group_index);
+        if (!$status ) {
+          $loaded_without_errors = FALSE;
+        }
+      } // end of foreach table in default data array
+
+    } //end of foreach line of file
+  } //end of foreach constant set
+
+  // check that data was inserted and update job_status
+  $sql = 'SELECT count(*) as num_tables FROM {tripal_bulk_loader_inserted} WHERE nid=%d GROUP BY nid';
+  $result = db_fetch_object(db_query($sql, $nid));
+  if ($result->num_tables > 0) {
+    $node->job_status = 'Data Inserted';
+    drupal_write_record('node', $node, 'nid');
+  }
+
+  // set the status of the job (in the node not the tripal jobs)
+  if ($loaded_without_errors) {
+      $status = 'Loading Completed Successfully';
+    }
+    else {
+      $status = 'Errors Encountered';
+      }
+  db_query("UPDATE {tripal_bulk_loader} SET job_status='%s' WHERE nid=%d", $status, $nid);
+
+}
+
+/**
+ *
+ *
+ */
+function process_data_array_for_line($priority, &$data, &$default_data, $field2column, $record2priority, $line, $nid, $line_num, $group_index) {
+  $table_data = $data[$priority];
+
+  $no_errors = TRUE;
+
+  $table = $table_data['table'];
+  $values = $table_data['values_array'];
+
+  //watchdog('T_bulk_loader','Original:<pre>'.print_r($table_data, TRUE).'</pre>', array(), WATCHDOG_NOTICE);
+
+  //print 'default values:'.print_r($values,TRUE)."\n";
+  if ($table_data['need_further_processing']) {
+    $values = tripal_bulk_loader_add_spreadsheetdata_to_values($values, $line, $field2column[$priority]);
+    if (!$values) {
+      watchdog('T_bulk_loader', 'Line ' . $line_num . ' Spreadsheet Added:' . print_r($values, TRUE), array(), WATCHDOG_NOTICE);
+    }
+
+    $values = tripal_bulk_loader_add_foreignkey_to_values($values, $data, $record2priority);
+    if (!$values) {
+      watchdog('T_bulk_loader', 'Line ' . $line_num . ' FK Added:<pre>' . print_r($values, TRUE) . print_r($data[$priority], TRUE) . '</pre>', array(), WATCHDOG_NOTICE);
+    }
+  }
+  $values = tripal_bulk_loader_regex_tranform_values($values, $table_data, $line);
+  if (!$values) {
+    watchdog('T_bulk_loader', 'Line ' . $line_num . ' Regex:<pre>' . print_r($values, TRUE) . print_r($table_data, TRUE) . '</pre>' . '</pre>', array(), WATCHDOG_NOTICE);
+  }
+
+  if (!$values) {
+<<<<<<< HEAD
+    $msg = 'Line ' . $line_num . ' ' . $table_data['record_id'] . ' (' . $table_data['mode'] . ') Aborted due to error in previous record. Values of current record:' . print_r($table_data['values_array'], TRUE);
+    watchdog('T_bulk_loader', $msg, array(), WATCHDOG_WARNING);
+    print "ERROR: " . $msg . "\n";
+=======
+    $msg = 'Line '.$line_num.' '.$table_data['record_id'].' ('.$table_data['mode'].') Aborted due to error in previous record. Values of current record:'.print_r($table_data['values_array'],TRUE);
+    watchdog('T_bulk_loader', $msg, array(), WATCHDOG_WARNING);
+    print "ERROR: ".$msg."\n";
+>>>>>>> 6.x-0.4-dev
+    $data[$priority]['error'] = TRUE;
+    $no_errors = FALSE;
+  }
+
+<<<<<<< HEAD
+  $table_desc = module_invoke_all('chado_' . $table . '_schema');
+=======
+  $table_desc = module_invoke_all('chado_'.$table.'_schema');
+>>>>>>> 6.x-0.4-dev
+  if (preg_match('/optional/', $table_array['mode'])) {
+    // Check all db required fields are set
+    $fields = $table_desc['fields'];
+    foreach ($fields as $field => $def) {
+      // a field is considered missing if it cannot be null and there is no default
+      // value for it or it is of type 'serial'
+<<<<<<< HEAD
+      if ($def['not null'] == 1 and !array_key_exists($field, $insert_values) and !isset($def['default']) and strcmp($def['type'], serial)!=0) {
+         $msg = 'Line ' . $line_num . ' ' . $table_data['record_id'] . ' (' . $table_data['mode'] . ') Missing Database Required Value: ' . $table . '.' . $field;
+=======
+      if($def['not null'] == 1 and !array_key_exists($field,$insert_values) and !isset($def['default']) and strcmp($def['type'],serial)!=0){
+         $msg = 'Line '.$line_num.' '.$table_data['record_id'].' ('.$table_data['mode'].') Missing Database Required Value: '.$table.'.'.$field;
+>>>>>>> 6.x-0.4-dev
+         watchdog('T_bulk_loader', $msg, array(), WATCHDOG_NOTICE);
+         $data[$priority]['error'] = TRUE;
+      }
+    }
+  } //end of if optional record
+
+  // Check required fields are present
+  foreach ($table_data['required'] as $field => $required) {
+    if ($required) {
+      if (!isset($values[$field])) {
+<<<<<<< HEAD
+        $msg = 'Line ' . $line_num . ' ' . $table_data['record_id'] . ' (' . $table_data['mode'] . ') Missing Template Required Value: ' . $table . '.' . $field;
+=======
+        $msg = 'Line '.$line_num.' '.$table_data['record_id'].' ('.$table_data['mode'].') Missing Template Required Value: '.$table.'.'.$field;
+>>>>>>> 6.x-0.4-dev
+        watchdog('T_bulk_loader', $msg, array(), WATCHDOG_NOTICE);
+        $data[$priority]['error'] = TRUE;
+      }
+    }
+  }
+
+  // add new values array into the data array
+  $data[$priority]['values_array'] = $values;
+
+  // check if it is already inserted
+  if ($table_data['inserted']) {
+    //watchdog('T_bulk_loader','Already Inserted:'.print_r($values,TRUE),array(),WATCHDOG_NOTICE);
+    return $no_errors;
+  }
+
+  // if there was an error already -> don't insert
+  if ($data[$priority]['error']) {
+    return $no_errors;
+  }
+
+  $header = '';
+  if (isset($values['feature_id'])) {
+    $header = $values['feature_id']['uniquename'] . ' ' . $table_data['record_id'];
+  }
+  else {
+    $header = $values['uniquename'] . ' ' . $table_data['record_id'];
+  }
+
+  // if insert unique then check to ensure unique
+  if (preg_match('/insert_unique/', $table_data['mode'])) {
+    $unique = tripal_core_chado_select($table, array_keys($table_desc['fields']), $values, array('has_record' => TRUE));
+    //print 'Unique?'.print_r(array('table' => $table, 'columns' => array_keys($table_desc['fields']), 'values' => $values),TRUE).' returns '.$unique."\n";
+    if ($unique > 0) {
+      //$default_data[$priority]['inserted'] = TRUE;
+      //watchdog('T_bulk_loader', $header.': Not unique ('.$unique.'):'.print_r($values,'values')."\n".print_r($data,TRUE),array(),WATCHDOG_NOTICE);;
+      return $no_errors;
+    }
+  }
+
+
+<<<<<<< HEAD
+  if (!preg_match('/select/', $table_data['mode'])) {
+=======
+  if (!preg_match('/select/',$table_data['mode'])) {
+>>>>>>> 6.x-0.4-dev
+    //watchdog('T_bulk_loader',$header.': Inserting:'.print_r($values, TRUE), array(), WATCHDOG_NOTICE);
+    if (variable_get('tripal_bulk_loader_prepare',TRUE)) {
+      $options = array('statement_name' => $priority);
+      if ($line_num == 1 && $group_index == 1) {
+        $options['prepare'] = TRUE;
+      }
+    }
+    else {
+      $options = array();
+    }
+
+    $record = tripal_core_chado_insert($table, $values, $options);
+
+    if (!$record) {
+<<<<<<< HEAD
+      $msg = 'Line ' . $line_num . ' ' . $table_data['record_id'] . ' (' . $table_data['mode'] . ') Unable to insert record into ' . $table . ' where values:' . print_r($values, TRUE);
+      watchdog('T_bulk_loader', $msg, array(), WATCHDOG_ERROR);
+      print "ERROR: " . $msg . "\n";
+=======
+      $msg = 'Line '.$line_num.' '.$table_data['record_id'].' ('.$table_data['mode'].') Unable to insert record into '.$table.' where values:'.print_r($values,TRUE);
+      watchdog('T_bulk_loader', $msg, array(), WATCHDOG_ERROR);
+      print "ERROR: ".$msg."\n";
+>>>>>>> 6.x-0.4-dev
+      $data[$priority]['error'] = TRUE;
+      $no_errors = FALSE;
+    }
+    else {
+      //add changes back to values array
+      $data[$priority]['values_array'] = $record;
+      $values = $record;
+
+      // if mode=insert_once then ensure we only insert it once
+      if (preg_match('/insert_once/', $table_data['mode'])) {
+        $default_data[$priority]['inserted'] = TRUE;
+      }
+
+      // add to tripal_bulk_loader_inserted
+      $insert_record = db_fetch_object(db_query(
+        "SELECT * FROM {tripal_bulk_loader_inserted} WHERE table_inserted_into='%s' AND nid=%d",
+        $table,
+        $nid
+      ));
+      if ($insert_record) {
+        $insert_record->ids_inserted .= ',' . $values[ $table_desc['primary key'][0] ];
+        drupal_write_record('tripal_bulk_loader_inserted', $insert_record, 'tripal_bulk_loader_inserted_id');
+        //print 'Update: '.print_r($insert_record,TRUE)."\n";
+        return $no_errors;
+      }
+      else {
+        $insert_record = array(
+          'nid' => $nid,
+          'table_inserted_into' => $table,
+          'table_primary_key' => $table_desc['primary key'][0],
+          'ids_inserted' => $values[ $table_desc['primary key'][0] ],
+        );
+        //print 'New: '.print_r($insert_record,TRUE)."\n";
+        $success = drupal_write_record('tripal_bulk_loader_inserted', $insert_record);
+        return $no_errors;
+      }//end of if insert record
+
+    } //end of if insert was successful
+  }
+  else {
+    $exists = tripal_core_chado_select($table, array_keys($table_desc['fields']), $values, array('has_record' => TRUE));
+    if (!$exists) {
+      // No record on select
+<<<<<<< HEAD
+      $msg = 'Line ' . $line_num . ' ' . $table_data['record_id'] . ' (' . $table_data['mode'] . ') No Matching record in ' . $table . ' where values:' . print_r($values, TRUE);
+=======
+      $msg = 'Line '.$line_num.' '.$table_data['record_id'].' ('.$table_data['mode'].') No Matching record in '.$table.' where values:'.print_r($values,TRUE);
+>>>>>>> 6.x-0.4-dev
+      watchdog('T_bulk_loader', $msg, array(), WATCHDOG_WARNING);
+      $data[$priority]['error'] = TRUE;
+    }
+  }
+  return $no_errors;
+}
+
+/**
+ * This function adds the file data to the values array
+ *
+ * @param $values
+ *   The default values array -contains all constants
+ * @param $line
+ *   An array of values for the current line
+ * @param $field2column
+ *   An array mapping values fields to line columns
+ * @return
+ *   Supplemented values array
+ */
+function tripal_bulk_loader_add_spreadsheetdata_to_values($values, $line, $field2column) {
+
+  foreach ($values as $field => $value) {
+<<<<<<< HEAD
+    if (is_array($value)) {
+      continue;
+    }
+
+    $column = $field2column[$field] - 1;
+    if ($column < 0) {
+      continue;
+    }
+
+    if (preg_match('/\S+/', $line[$column])) {
+=======
+    if (is_array($value)) { continue; }
+
+    $column = $field2column[$field] - 1;
+    if ($column < 0) { continue; }
+
+    if (preg_match('/\S+/',$line[$column])) {
+>>>>>>> 6.x-0.4-dev
+      $values[$field] = $line[$column];
+    }
+    else {
+      unset($values[$field]);
+    }
+  }
+
+  return $values;
+}
+
+/**
+ * Handles foreign keys in the values array.
+ *
+ * Specifically, if the value for a field is an array then it is assumed that the array contains
+ * the name of the record whose values array should be substituted here. Thus the foreign
+ * record is looked up and the values array is substituted in.
+ *
+ */
+function tripal_bulk_loader_add_foreignkey_to_values($values, $data, $record2priority) {
+
+  foreach ($values as $field => $value) {
+    if (is_array($value)) {
+      $foreign_record = $value['foreign record'];
+      $foreign_priority = $record2priority[$foreign_record];
+      $foreign_values = $data[$foreign_priority]['values_array'];
+
+      // add to current values array
+      $values[$field] = $foreign_values;
+    }
+  }
+
+  return $values;
+}
+
+/**
+ * Uses a supplied regex to transform spreadsheet values
+ *
+ * @param $values
+ *   The select/insert values array for the given table
+ * @param $table_data
+ *   The data array for the given table
+ */
+function tripal_bulk_loader_regex_tranform_values($values, $table_data, $line) {
+
+  if (empty($table_data['regex_transform']) OR !is_array($table_data['regex_transform'])) {
+    return $values;
+  }
+
+<<<<<<< HEAD
+  //watchdog('T_bulk_loader','Regex Transformation:<pre>'.print_r($table_data['regex_transform'], TRUE).'</pre>', array(), WATCHDOG_NOTICE);
+
+  foreach ($table_data['regex_transform'] as $field => $regex_array) {
+    if (!is_array($regex_array['replace'])) {
+       continue;
+     }
+=======
+  if (empty($table_data['regex_transform']) OR !is_array($table_data['regex_transform'])) { return $values; }
+
+  //watchdog('T_bulk_loader','Regex Transformation:<pre>'.print_r($table_data['regex_transform'], TRUE).'</pre>', array(), WATCHDOG_NOTICE);
+
+  foreach ($table_data['regex_transform'] as $field => $regex_array) {
+    if (!is_array($regex_array['replace'])) { continue; }
+>>>>>>> 6.x-0.4-dev
+
+    //print 'Match:'.print_r($regex_array['pattern'],TRUE)."\n";
+    //print 'Replace:'.print_r($regex_array['replace'],TRUE)."\n";
+    //print 'Was:'.$values[$field]."\n";
+
+    // Check for <#column:\d+#> notation
+    // if present replace with that column in the current line
+    foreach ($regex_array['replace'] as $key => $replace) {
+      if (preg_match_all('/<#column:(\d+)#>/', $replace, $matches)) {
+        foreach ($matches[1] as $k => $column_num) {
+          $replace = preg_replace('/' . $matches[0][$k] .'/', $line[$column_num-1], $replace);
+        }
+        $regex_array['replace'][$key] = $replace;
+      }
+    }
+
+    // do the full replacement
+    $old_value = $values[$field];
+    $new_value = preg_replace($regex_array['pattern'], $regex_array['replace'], $old_value);
+    $values[$field] = $new_value;
+
+    if ($values[$field] === '') {
+      unset($values[$field]);
+    }
+    //print 'Now:'.$values[$field]."\n";
+  }
+
+
+
+  return $values;
+}
+
+/**
+ * Flattens an array up to two levels
+ * Used for printing of arrays without taking up much space
+ */
+function tripal_bulk_loader_flatten_array($values) {
+  $flattened_values = array();
+
+  foreach ($values as $k => $v) {
+    if (is_array($v)) {
+      $vstr = array();
+      foreach ($v as $vk => $vv) {
+        if (strlen($vv) > 20) {
+          $vstr[] = $vk . '=>' . substr($vv, 0, 20) . '...';
+        }
+        else {
+          $vstr[] = $vk . '=>' . $vv;
+        }
+      }
+      $v = '{' . implode(',', $vstr) . '}';
+    }
+    elseif (strlen($v) > 20) {
+      $v = substr($v, 0, 20) . '...';
+    }
+    $flattened_values[] = $k . '=>' . $v;
+  }
+
+<<<<<<< HEAD
+  return implode(', ', $flattened_values);
+}
+=======
+  return implode(', ',$flattened_values);
+}
+>>>>>>> 6.x-0.4-dev

+ 1 - 0
tripal_bulk_loader/tripal_bulk_loader.module

@@ -45,6 +45,7 @@ function tripal_bulk_loader_menu() {
       'type' => MENU_CALLBACK,
       'file' => 'tripal_bulk_loader.constants.inc',
    );
+
    // Admin page to create the template
    $items['admin/tripal/tripal_bulk_loader_template'] = array(
       'title' => 'Bulk Loader Template',

+ 647 - 0
tripal_bulk_loader/tripal_bulk_loader.module.orig

@@ -0,0 +1,647 @@
+<?php
+
+include('tripal_bulk_loader.loader.inc');
+include('tripal_bulk_loader.constants.inc');
+
+/**
+ * Implements hook_init
+ * Used to add stylesheets and javascript files to the header
+ */
+function tripal_bulk_loader_init() {
+  // Add javascript and style sheet
+  drupal_add_css(drupal_get_path('theme', 'tripal') . '/css/tripal_bulk_loader.css');
+  drupal_add_js(drupal_get_path('theme', 'tripal') . '/js/tripal_bulk_loader.js');
+}
+
+/**
+ * Implements hook_menu
+ */
+function tripal_bulk_loader_menu() {
+  $items = array();
+   // Show all loaders
+   $items['tripal_bulk_loaders'] = array(
+     'title' => 'Tripal Bulk Loaders',
+     'description' => 'Tripal bulk loaders for loading tab-delimited file into chado database',
+     'page callback' => 'tripal_bulk_loader_list',
+     'access arguments' => array('access tripal_bulk_loader'),
+     'type' => MENU_NORMAL_ITEM,
+   );
+   // Bulk Loading Job Node
+   $items['node/%node/constants/%/edit'] = array(
+      'title' => 'Edit Constant Set',
+      'description' => 'Edit a group of constants associated with the current bulk loader',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_edit_constant_set_form', 1, 3),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+<<<<<<< HEAD
+      'file' => 'tripal_bulk_loader.constants.inc',
+=======
+		  'file' => 'tripal_bulk_loader.constants.inc',
+>>>>>>> 6.x-0.4-dev
+   );
+   $items['node/%node/constants/%/delete'] = array(
+      'title' => 'Delete Constant Set',
+      'description' => 'Delete a group of constants associated with the current bulk loader',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_delete_constant_set_form', 1, 3),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+<<<<<<< HEAD
+      'file' => 'tripal_bulk_loader.constants.inc',
+=======
+		  'file' => 'tripal_bulk_loader.constants.inc',
+>>>>>>> 6.x-0.4-dev
+   );
+
+   // Admin page to create the template
+   $items['admin/tripal/tripal_bulk_loader_template'] = array(
+      'title' => 'Bulk Loader Template',
+      'description' => 'Templates for loading tab-delimited data',
+      'page callback' => 'tripal_bulk_loader_admin_template',
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_NORMAL_ITEM,
+<<<<<<< HEAD
+      'file' => 'tripal_bulk_loader.admin.inc',
+  );
+  // Create/Edit Template -------
+=======
+		  'file' => 'tripal_bulk_loader.admin.inc',
+	);
+   $items['admin/tripal/tripal_bulk_loader_template/configure'] = array(
+      'title' => 'Configuration',
+      'description' => 'Configure the Tripal Bulk Loader Module',
+    	'page callback' => 'drupal_get_form',
+    	'page arguments' => array('tripal_bulk_loader_configuration_form'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_NORMAL_ITEM,
+		  'file' => 'tripal_bulk_loader.admin.inc',
+	);
+
+	// Create/Edit Template -------
+>>>>>>> 6.x-0.4-dev
+  $items['admin/tripal/tripal_bulk_loader_template/create'] = array(
+      'title' => 'Create Bulk Loader Template',
+      'description' => 'Create loader template for loading tab-delimited data',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_modify_template_base_form', 'create'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_NORMAL_ITEM,
+<<<<<<< HEAD
+    'file' => 'tripal_bulk_loader.admin.inc',
+=======
+		'file' => 'tripal_bulk_loader.admin.inc',
+>>>>>>> 6.x-0.4-dev
+  );
+  $items['admin/tripal/tripal_bulk_loader_template/edit'] = array(
+      'title' => 'Edit Bulk Loader Template',
+      'description' => 'Edit loader template for loading tab-delimited data',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_modify_template_base_form', 'edit'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_NORMAL_ITEM,
+<<<<<<< HEAD
+      'file' => 'tripal_bulk_loader.admin.inc',
+=======
+		  'file' => 'tripal_bulk_loader.admin.inc',
+>>>>>>> 6.x-0.4-dev
+  );
+  $items['admin/tripal/tripal_bulk_loader_template/edit_record'] = array(
+      'title' => 'Edit Template Record',
+      'description' => 'Edit a record in an existing tripal bulk loader template.',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_edit_template_record_form'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+<<<<<<< HEAD
+    'file' => 'tripal_bulk_loader.admin.inc',
+  );
+  $items['admin/tripal/tripal_bulk_loader_template/add_field'] = array(
+=======
+		'file' => 'tripal_bulk_loader.admin.inc',
+	);
+	$items['admin/tripal/tripal_bulk_loader_template/add_field'] = array(
+>>>>>>> 6.x-0.4-dev
+      'title' => 'Add Template Field',
+      'description' => 'Add a template field to an existing tripal bulk loader template.',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_add_template_field_form'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+<<<<<<< HEAD
+    'file' => 'tripal_bulk_loader.admin.inc',
+  );
+  $items['admin/tripal/tripal_bulk_loader_template/edit_field'] = array(
+=======
+		'file' => 'tripal_bulk_loader.admin.inc',
+	);
+	$items['admin/tripal/tripal_bulk_loader_template/edit_field'] = array(
+>>>>>>> 6.x-0.4-dev
+      'title' => 'Edit Template Field',
+      'description' => 'Edit an existing field from a tripal bulk loader template.',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_edit_template_field_form'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+<<<<<<< HEAD
+    'file' => 'tripal_bulk_loader.admin.inc',
+  );
+  // Delete Template -----
+  $items['admin/tripal/tripal_bulk_loader_template/delete'] = array(
+=======
+		'file' => 'tripal_bulk_loader.admin.inc',
+	);
+	// Delete Template -----
+	$items['admin/tripal/tripal_bulk_loader_template/delete'] = array(
+>>>>>>> 6.x-0.4-dev
+      'title' => 'Delete Bulk Loader Template',
+      'description' => 'Delete bulk loader template',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_delete_template_base_form'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_NORMAL_ITEM,
+<<<<<<< HEAD
+    'file' => 'tripal_bulk_loader.admin.inc',
+  );
+  // Import/Export ---------
+=======
+		'file' => 'tripal_bulk_loader.admin.inc',
+	);
+	// Import/Export ---------
+>>>>>>> 6.x-0.4-dev
+  $items['admin/tripal/tripal_bulk_loader_template/import'] = array(
+      'title' => 'Import Bulk Loader Template',
+      'description' => 'Import Loaders',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_import_export_template_form', 'import'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_NORMAL_ITEM,
+<<<<<<< HEAD
+      'file' => 'tripal_bulk_loader.admin.inc',
+=======
+		  'file' => 'tripal_bulk_loader.admin.inc',
+>>>>>>> 6.x-0.4-dev
+  );
+  $items['admin/tripal/tripal_bulk_loader_template/export'] = array(
+      'title' => 'Export Bulk Loader Template',
+      'description' => 'Export Loaders',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('tripal_bulk_loader_import_export_template_form', 'export'),
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_NORMAL_ITEM,
+<<<<<<< HEAD
+      'file' => 'tripal_bulk_loader.admin.inc',
+  );
+  // AHAH ---------
+  $items['admin/tripal/tripal_bulk_loader_template/add_field_ahah'] = array(
+      'page callback' => 'tripal_bulk_loader_add_field_ahah',
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+      'file' => 'tripal_bulk_loader.admin.inc',
+  );
+  $items['admin/tripal/tripal_bulk_loader_template/edit_field_ahah'] = array(
+      'page callback' => 'tripal_bulk_loader_edit_field_ahah',
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+      'file' => 'tripal_bulk_loader.admin.inc',
+  );
+=======
+		  'file' => 'tripal_bulk_loader.admin.inc',
+  );
+	// AHAH ---------
+	$items['admin/tripal/tripal_bulk_loader_template/add_field_ahah'] = array(
+      'page callback' => 'tripal_bulk_loader_add_field_ahah',
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+		  'file' => 'tripal_bulk_loader.admin.inc',
+	);
+	$items['admin/tripal/tripal_bulk_loader_template/edit_field_ahah'] = array(
+      'page callback' => 'tripal_bulk_loader_edit_field_ahah',
+      'access arguments' => array('administer site configuration'),
+      'type' => MENU_CALLBACK,
+		  'file' => 'tripal_bulk_loader.admin.inc',
+	);
+>>>>>>> 6.x-0.4-dev
+
+  return $items;
+}
+
+
+/**
+ * Implements hook_theme
+ */
+function tripal_bulk_loader_theme() {
+  return array(
+    'tripal_bulk_loader_set_constants_form' => array(
+      'arguments' => array('form' => NULL),
+    ),
+    'tripal_bulk_loader_template' => array(
+      'arguments' => array('template_id' => NULL),
+      'template' => 'tripal_bulk_loader_template'
+    ),
+    'tripal_bulk_loader_modify_template_base_form' => array(
+      'arguments' => array('form' => NULL),
+      'template' => 'tripal_bulk_loader_modify_template_base_form',
+    ),
+    'tripal_bulk_loader_edit_template_field_form' => array(
+      'arguments' => array('form' => NULL),
+      'template' => 'tripal_bulk_loader_edit_template_field_form',
+    ),
+    'tripal_bulk_loader_add_template_field_form' => array(
+      'arguments' => array('form' => NULL),
+      'template' => 'tripal_bulk_loader_add_template_field_form',
+    ),
+  );
+}
+
+/**
+ *  Implements hook_access
+ */
+function tripal_bulk_loader_access($op, $node, $account) {
+  if ($op == 'create') {
+    if (!user_access('create tripal_bulk_loader', $account)) {
+         return FALSE;
+      }
+  }
+  if ($op == 'update') {
+    if (!user_access('edit tripal_bulk_loader', $account)) {
+      return FALSE;
+    }
+  }
+  if ($op == 'delete') {
+    if (!user_access('delete tripal_bulk_loader', $account)) {
+      return FALSE;
+    }
+  }
+  if ($op == 'view') {
+    if (!user_access('access tripal_bulk_loader', $account)) {
+      return FALSE;
+    }
+  }
+  return NULL;
+}
+
+/**
+ * Implements hook_perm
+ */
+function tripal_bulk_loader_perm() {
+  return array(
+      'access tripal_bulk_loader',
+      'create tripal_bulk_loader',
+      'delete tripal_bulk_loader',
+      'edit tripal_bulk_loader',
+  );
+}
+
+/**
+ * Creates a listing page for all bulk loading jobs
+ */
+function tripal_bulk_loader_list() {
+  $num_results_per_page = 50;
+  $output = '';
+
+<<<<<<< HEAD
+  $header = array('', 'Status', 'Loader', 'File');
+=======
+  $header = array('','Status','Loader','File');
+>>>>>>> 6.x-0.4-dev
+  $rows = array();
+
+  $query = 'SELECT * FROM {tripal_bulk_loader} l '
+    .'LEFT JOIN {node} n ON n.nid = l.nid '
+    .'LEFT JOIN {tripal_bulk_loader_template} t ON t.template_id = cast(l.template_id as integer)';
+  $resource = pager_query($query, $num_results_per_page, 0, NULL);
+  while ($r = db_fetch_object($resource)) {
+    $row = array(
+      l($r->title, 'node/' . $r->nid),
+      $r->job_status,
+      $r->name,
+      $r->file
+    );
+    $rows[] = $row;
+  }
+
+  $output .= theme('table', $header, $rows);
+  return $output;
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+// Node Functions
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Implements hook_node_info
+ */
+function tripal_bulk_loader_node_info() {
+  $nodes = array();
+  $nodes['tripal_bulk_loader'] = array(
+      'name' => t('Bulk Loading Job'),
+      'module' => 'tripal_bulk_loader',
+      'description' => t('A bulk loader for inserting tab-delimited data into chado database'),
+      'has_title' => TRUE,
+      'has_body' => FALSE,
+      'locked' => TRUE
+  );
+  return $nodes;
+}
+
+/**
+ * Implements node_form
+ * Used to gather the extra details stored with a Bulk Loading Job Node
+ */
+function tripal_bulk_loader_form($node, $form_state) {
+  $form = array();
+
+  if (isset($form_state['values'])) {
+    $node = $form_state['values'] + (array)$node;
+    $node = (object) $node;
+  }
+
+  $sql = "SELECT * FROM {tripal_bulk_loader_template}";
+  $results = db_query($sql);
+  $templates = array();
+  while ($template = db_fetch_object ($results)) {
+    $templates [$template->template_id] = $template->name;
+  }
+
+  if (!$templates) {
+    $form['label'] = array(
+    '#type' => 'item',
+      '#description' => t("Loader template needs to be created before any bulk loader can be added. Go to 'Tripal Management > Bulk Loader Template' to create the template."),
+      '#weight'        => -10,
+    );
+
+    return $form;
+  }
+
+  $form['loader'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Basic Details'),
+  );
+
+  $form['loader']['loader_name'] = array(
+    '#type'          => 'textfield',
+    '#title'         => t('Loading Job Name'),
+    '#weight'        => -10,
+    '#required'      => TRUE,
+    '#default_value' => $node->loader_name
+  );
+
+  $form['loader']['template_id'] = array(
+    '#type' => 'select',
+    '#title' => t('Template'),
+    '#description'   => t('Please specify a template for this loader'),
+    '#options'       => $templates,
+    '#weight'        => -9,
+    '#required'      => TRUE,
+    '#default_value' => $node->template_id,
+  );
+
+  $form['loader']['file']= array(
+    '#type'          => 'textfield',
+    '#title'         => t('Data File'),
+    '#description'   => t('Please specify the data file to be loaded.'),
+    '#weight'        => -8,
+    '#default_value' => $node->file
+  );
+
+  $form['loader']['has_header'] = array(
+    '#type' => 'radios',
+    '#title' => t('File has a Header'),
+    '#options' => array( 1 => 'Yes', 2 => 'No'),
+    '#weight' => -7,
+    '#default_value' => $node->file_has_header,
+  );
+
+  return $form;
+}
+
+
+/**
+ * Implements node_load
+ */
+function tripal_bulk_loader_load($node) {
+  $sql = "SELECT * FROM {tripal_bulk_loader} WHERE nid = %d";
+  $node = db_fetch_object(db_query($sql, $node->nid));
+
+<<<<<<< HEAD
+  $node->title = 'Bulk Loading Job: ' . $node->loader_name;
+
+  // Add the loader template
+  $sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+  $results = db_fetch_object(db_query($sql, $node->template_id));
+  $template = unserialize($results->template_array);
+  $node->template = $results;
+  $node->template->template_array = $template;
+=======
+	$node->title = 'Bulk Loading Job: '.$node->loader_name;
+
+	// Add the loader template
+	$sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+	$results = db_fetch_object(db_query($sql, $node->template_id));
+	$template = unserialize($results->template_array);
+	$node->template = $results;
+	$node->template->template_array = $template;
+>>>>>>> 6.x-0.4-dev
+
+  // Add inserted records
+  $sql = 'SELECT * FROM {tripal_bulk_loader_inserted} WHERE nid=%d';
+  $resource = db_query($sql, $node->nid);
+  while ($r = db_fetch_object($resource)) {
+<<<<<<< HEAD
+    $r->num_inserted = sizeof(preg_split('/,/', $r->ids_inserted));
+=======
+    $r->num_inserted = sizeof(preg_split('/,/',$r->ids_inserted));
+>>>>>>> 6.x-0.4-dev
+    $node->inserted_records->{$r->table_inserted_into} = $r;
+  }
+
+  // Add exposed field list
+  $node->exposed_fields = array();
+  if ($template) {
+    foreach ($template as $record_id => $record) {
+      foreach ($record['fields'] as $field_id => $field) {
+        if ($field['exposed']) {
+          $node->exposed_fields[] = array(
+            'record_id' => $record_id,
+            'field_id' => $field_id,
+            'title' => $field['title'],
+          );
+        }
+      }
+    }
+
+    if (empty($node->exposed_fields)) {
+      $node->exposed_fields[] = array();
+    }
+  }
+
+
+  // Add constants
+  $sql = 'SELECT * FROM {tripal_bulk_loader_constants} WHERE nid=%d ORDER BY group_id, record_id, field_id';
+  $resource = db_query($sql, $node->nid);
+  while ($r = db_fetch_object($resource)) {
+    $node->constants[$r->group_id][$r->record_id][$r->field_id] = array(
+      'constant_id' => $r->constant_id,
+      'group_id' => $r->group_id,
+<<<<<<< HEAD
+      'chado_table' => $r->chado_table,
+      'chado_field' => $r->chado_field,
+      'record_id' => $r->record_id,
+      'field_id' => $r->field_id,
+      'value' => $r->value
+=======
+      'chado_table'=>$r->chado_table,
+      'chado_field'=>$r->chado_field,
+      'record_id'=>$r->record_id,
+      'field_id'=>$r->field_id,
+      'value'=>$r->value
+>>>>>>> 6.x-0.4-dev
+    );
+  }
+  if (!$node->constants) {
+    $node->constants[] = array();
+  }
+
+<<<<<<< HEAD
+  return $node;
+=======
+	return $node;
+>>>>>>> 6.x-0.4-dev
+}
+
+/**
+ * Implements node_insert
+ * Insert the data from the node form on Create content
+ */
+<<<<<<< HEAD
+function tripal_bulk_loader_insert($node) {
+=======
+function tripal_bulk_loader_insert ($node) {
+>>>>>>> 6.x-0.4-dev
+
+  // Insert into tripal_bulk_loader
+  $sql = "INSERT INTO {tripal_bulk_loader} (nid, loader_name, template_id, file, file_has_header, job_status) VALUES (%d, '%s', %d, '%s', %d, '%s')";
+  db_query($sql, $node->nid, $node->loader_name, $node->template_id, $node->file, $node->has_header, 'Initialized');
+
+<<<<<<< HEAD
+  // Update title
+  $node->title =$node->loader_name;
+  drupal_write_record('node', $node, 'nid');
+  drupal_write_record('node_revision', $node, 'nid');
+=======
+	// Update title
+	$node->title =$node->loader_name;
+	drupal_write_record('node',$node,'nid');
+	drupal_write_record('node_revision',$node,'nid');
+>>>>>>> 6.x-0.4-dev
+
+  drupal_set_message('After reviewing the details, please Submit this Job (by clicking the "Submit Job" button below). No data will be loaded until the submitted job is reached in the queue.');
+
+}
+
+/**
+ * Implements node_delete
+ * Deletes the data when the delete button on the node form is clicked
+ */
+function tripal_bulk_loader_delete($node) {
+  $sql = "DELETE FROM {tripal_bulk_loader} WHERE nid = %d";
+  db_query($sql, $node->nid);
+}
+
+/**
+ * Implements node_update
+ * Updates the data submitted by the node form on edit
+ */
+<<<<<<< HEAD
+function tripal_bulk_loader_update($node) {
+
+  // Update tripal_bulk_loader
+  $sql = "UPDATE {tripal_bulk_loader} SET nid = %d, loader_name = '%s', template_id = %d, file = '%s', file_has_header = '%s' WHERE nid = %d";
+  db_query($sql, $node->nid, $node->loader_name, $node->template_id, $node->file, $node->has_header, $node->nid);
+
+  // Add a job if the user want to load the data
+  global $user;
+  if ($node->job) {
+    $job_args[0] =$node->loader_name;
+    $job_args[1] = $node->template_id;
+    $job_args[2] = $node->file;
+    if (is_readable($node->file)) {
+      $fname = preg_replace("/.*\/(.*)/", "$1", $node->file);
+      tripal_add_job("Bulk Load: $fname", 'tripal_bulk_loader', 'tripal_bulk_loader_load_data', $job_args, $user->uid);
+    }
+    else {
+      drupal_set_message(t("Can not open %file. Job not scheduled.", array('%file' => $node->file)));
+    }
+  }
+=======
+function tripal_bulk_loader_update ($node) {
+
+  // Update tripal_bulk_loader
+	$sql = "UPDATE {tripal_bulk_loader} SET nid = %d, loader_name = '%s', template_id = %d, file = '%s', file_has_header = '%s' WHERE nid = %d";
+	db_query($sql, $node->nid, $node->loader_name, $node->template_id, $node->file, $node->has_header, $node->nid);
+
+	// Add a job if the user want to load the data
+	global $user;
+	if($node->job) {
+		$job_args[0] =$node->loader_name;
+		$job_args[1] = $node->template_id;
+		$job_args[2] = $node->file;
+		if (is_readable($node->file)) {
+			$fname = preg_replace("/.*\/(.*)/", "$1", $node->file);
+			tripal_add_job("Bulk Load: $fname",'tripal_bulk_loader', 'tripal_bulk_loader_load_data', $job_args, $user->uid);
+		} else {
+			drupal_set_message("Can not open $node->file. Job not scheduled.");
+		}
+	}
+>>>>>>> 6.x-0.4-dev
+
+}
+
+///////////////////////////////////////////////////////////
+
+/**
+ * Preprocessor function for the tripal_bulk_loader template
+ */
+function tripal_bulk_loader_preprocess_tripal_bulk_loader_template(&$variables) {
+
+  $sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+  $template = db_fetch_object(db_query($sql, $variables['template_id']));
+  $template->template_array = unserialize($template->template_array);
+  $variables['template'] = $template;
+
+<<<<<<< HEAD
+=======
+	$sql = "SELECT * FROM {tripal_bulk_loader_template} WHERE template_id=%d";
+	$template = db_fetch_object(db_query($sql, $variables['template_id']));
+	$template->template_array = unserialize($template->template_array);
+	$variables['template'] = $template;
+
+>>>>>>> 6.x-0.4-dev
+}
+
+/**
+ * Implements hook_job_describe_args()
+ * Specifically to make viewing past tripal jobs more readable for jobs registered by this module
+ *
+ * @params $callback
+ *   The callback passed into tripal_add_job()
+ * @param $args
+ *   The arguements passed into tripal_add_job()
+ * @return
+ *   An array where keys are the human readable headers describing each arguement
+ *   and the value is the aguement passed in after formatting
+ */
+function tripal_bulk_loader_job_describe_args($callback, $args) {
+
+  $new_args = array();
+  if ($callback == 'tripal_bulk_loader_load_data') {
+    //1st arg is the nid for a bulk loader node
+    $node = node_load($args[0]);
+    $new_args['Bulk Loading Job'] = l($node->title, 'node/' . $args[0]);
+    return $new_args;
+  }
+
+}
+

+ 141 - 29
tripal_core/tripal_core.api.inc

@@ -104,6 +104,21 @@ require_once "tripal_core.schema.api.inc";
  */
 function tripal_core_chado_insert($table, $values) {
   $insert_values = array();
+  $chado_db = tripal_db_persistent_chado();
+
+  // Determine plan of action
+  if ($options['statement_name']) {
+    $prepared = TRUE;
+    if ($options['prepare']) {
+      $build_sql = TRUE;
+    }
+    else {
+      $build_sql = FALSE;
+    }
+  }
+  else {
+    $build_sql = TRUE;
+  }
 
   // get the table description
   $table_desc = module_invoke_all('chado_' . $table . '_schema');
@@ -177,47 +192,101 @@ function tripal_core_chado_insert($table, $values) {
   }
 
   // Now build the insert SQL statement
-  $ifields = array();
-  $ivalues = array();
-  $itypes = array();
-  foreach ($insert_values as $field => $value) {
-    array_push($ifields, $field);
-    array_push($ivalues, $value);
-    if (strcmp($value, '__NULL__') == 0) {
-      array_push($itypes, "NULL");
+  $ifields = array(); //contains the names of the fields
+  $ivalues = array(); //contains the values of the fields
+  $itypes = array(); // contains %d/%s placeholders for the sql query
+  $iplaceholders = array(); // contains $1/$2 placeholders for the prepare query
+  $idatatypes = array(); //contains the data type of the fields (int, text, etc.)
+  $i = 1;
+  foreach ($insert_values as $field => $value){
+    $ifields[] = $field;
+    $ivalues[] = $value;
+    $iplaceholders[] = '$'.$i;
+    $i++;
+    if(strcmp($value,'__NULL__')==0){
+      $itypes[] = "NULL";
+      $idatatypes[] = "NULL";
     }
-    elseif (strcmp($fields[$field]['type'], 'serial') == 0 or
-      strcmp($fields[$field]['type'], 'int') == 0) {
-      array_push($itypes, "%d");
+    elseif(strcmp($fields[$field]['type'],'serial')==0 or
+      strcmp($fields[$field]['type'],'int')==0){
+      $itypes[] = "%d";
+      $idatatypes[] = 'int';
     }
     else {
-      array_push($itypes, "'%s'");
+      $itypes[] = "'%s'";
+      $idatatypes[] = 'text';
+    }
+  }
+
+  if ($build_sql) {
+    // prepare the statement
+    if ($prepared) {
+      $prepare_sql = "PREPARE " . $options['statement_name'] . " (" . implode(', ', $idatatypes) . ") AS INSERT INTO {$table} (" . implode(", ", $ifields) . ") VALUES (" . implode(", ", $iplaceholders) . ")";
+
+      $previous_db = tripal_db_set_active('chado');
+      $status = db_query($prepare_sql);
+      tripal_db_set_active($previous_db);
+
+      if (!$status) {
+        watchdog('tripal_core',"tripal_core_chado_insert: not able to prepare '%name' statement for: %sql", array('%name' => $options['statement_name'], '%sql' => $sql), 'WATCHDOG ERROR');
+        return FALSE;
+       }
+    } else {
+      $sql = "INSERT INTO {$table} (" . implode(", ",$ifields) . ") VALUES (". implode(", ",$itypes) .")";
     }
   }
-  $sql = "INSERT INTO {$table} (" . implode(", ", $ifields) . ") VALUES (". implode(", ", $itypes) .")";
 
   // finally perform the insert.
-  $previous_db = tripal_db_set_active('chado');  // use chado database
-  $result = db_query($sql, $ivalues);
-  tripal_db_set_active($previous_db);  // now use drupal database
-  if ($result) {
-    // add primary keys to values before return
-    $primary_key = array();
-    if (!is_array($table_desc['primary key'])) {
-      $table_desc['primary key'] = array();
-      watchdog('tripal_core', "tripal_core_chado_insert: %table not defined in tripal schema api", array('%table' => $table), 'WATCHDOG WARNING');
+  if ($prepared) {
+
+    $sql = "EXECUTE " . $options['statement_name'] . "(" . implode(", ", $itypes) . ")";
+
+    $previous_db = tripal_db_set_active('chado');
+    $result = db_query($sql, $ivalues);
+    tripal_db_set_active($previous_db);
+    if ($result) {
+      // add primary keys to values before return
+      $primary_key = array();
+      if (!is_array($table_desc['primary key'])) {
+        $table_desc['primary key'] = array();
+        watchdog('tripal_core',"tripal_core_chado_insert: %table not defined in tripal schema api", array('%table' => $table), 'WATCHDOG WARNING');
+      }
+      foreach ($table_desc['primary key'] as $field) {
+        $value = db_last_insert_id($table, $field);
+        $values[$field] = $value;
+      }
+      return $values;
     }
-    foreach ($table_desc['primary key'] as $field) {
-      $value = db_last_insert_id($table, $field);
-      $values[$field] = $value;
+    else {
+      watchdog('tripal_core',"tripal_core_chado_insert: not able to execute prepared statement '%name' with values: %values", array('%name' => $options['statement_name'], '%values' => print_r($values,1)), 'WATCHDOG ERROR');
+      return FALSE;
     }
-    return $values;
   }
   else {
-    watchdog('tripal_core', "tripal_core_chado_insert: Cannot insert record into $table table: " . print_r($values, 1), array(), 'WATCHDOG_ERROR');
-    return FALSE;
+    $previous_db = tripal_db_set_active('chado');  // use chado database
+    $result = db_query($sql, $ivalues);
+    tripal_db_set_active($previous_db);  // now use drupal database
+    if ($result) {
+      // add primary keys to values before return
+      $primary_key = array();
+      if (!is_array($table_desc['primary key'])) {
+        $table_desc['primary key'] = array();
+        watchdog('tripal_core', "tripal_core_chado_insert: %table not defined in tripal schema api", array('%table' => $table), 'WATCHDOG WARNING');
+      }
+      foreach ($table_desc['primary key'] as $field) {
+        $value = db_last_insert_id($table, $field);
+        $values[$field] = $value;
+      }
+      return $values;
+    }
+    else {
+      watchdog('tripal_core', "tripal_core_chado_insert: Cannot insert record into $table table: " . print_r($values, 1), array(), 'WATCHDOG_ERROR');
+      return FALSE;
+    }
   }
+
   return FALSE;
+
 }
 
 /**
@@ -1781,6 +1850,48 @@ function tripal_db_set_active($dbname) {
   }
 }
 
+
+/**
+ * Instantiate or Return a persistent chado connection
+ *
+ * NOTE: cannot use $active_db since a new connection is created each time
+ * db_set_active() is called
+ *
+ * @return
+ *   A postgresql connection object which can be used by pg_prepare, pg_execute, etc.
+ */
+function tripal_db_persistent_chado () {
+  global $db_url;
+
+  // get connection if it already exists
+  $connection = variable_get('tripal_perisistent_chado',NULL);
+
+  if ($connection) {
+    return $connection;
+
+  // Otherwise we need to set it
+  } else {
+    if (is_array($db_url) && isset($db_url['chado'])) {
+      $connection = db_connect($db_url['chado']);
+      variable_set('tripal_perisistent_chado', $connection);
+    } else {
+      $connection = db_connect($db_url);
+      variable_set('tripal_perisistent_chado', $connection);
+    }
+
+    return $connection;
+  }
+  return FALSE;
+}
+
+/**
+ * Release a persistent chado connection
+ */
+function tripal_db_release_persistent_chado () {
+  variable_del('tripal_perisistent_chado');
+}
+
+
 /**
  * Purpose: Get max rank for a given set of criteria
  *   This function was developed with the many property tables in chado in mind
@@ -1957,4 +2068,5 @@ function tripal_core_chado_schema_exists() {
   else {
     return FALSE;
   }
-}
+}
+