Browse Source

Fixed bug in TripalField validate. Added the annotation field

Stephen Ficklin 7 years ago
parent
commit
9749e320fd

+ 1 - 5
tripal/includes/TripalFields/TripalField.inc

@@ -422,10 +422,6 @@ class TripalField {
    *    The type of $entity.
    *  @param $entity
    *    The entity for the operation.
-   *  @param $field
-   *    The field structure for the operation.
-   *  @param $instance
-   *    The instance structure for $field on $entity's bundle.
    *  @param $langcode
    *    The language associated with $items.
    *  @param $items
@@ -440,7 +436,7 @@ class TripalField {
    *      - message: The human readable message to be displayed.
    *
    */
-  public function validate($entity_type, $entity, $field, $items, &$errors) {
+  public function validate($entity_type, $entity, $langcode, $items, &$errors) {
 
   }
 

+ 1 - 1
tripal/includes/tripal.fields.inc

@@ -810,7 +810,7 @@ function tripal_field_validate($entity_type, $entity, $field, $instance,
    $field_type = $field['type'];
    if (tripal_load_include_field_class($field_type)) {
      $tfield = new $field_type($field, $instance);
-     $tfield->validate($entity_type, $entity, $langcode,$items, $errors);
+     $tfield->validate($entity_type, $entity, $langcode, $items, $errors);
    }
 }
 

+ 0 - 1
tripal_chado/includes/TripalFields/chado_linker__contact/chado_linker__contact_widget.inc

@@ -118,6 +118,5 @@ class chado_linker__contact_widget extends ChadoFieldWidget {
       $form_state['values'][$field_name][$langcode][$delta]['chado-' . $chado_table . '__contact_id'] = $contact->contact_id;
       $form_state['values'][$field_name][$langcode][$delta]['value'] = $name;
     }
-    dpm($form_state['values']);
   }
 }

+ 1 - 1
tripal_chado/includes/TripalFields/data__accession/data__accession.inc

@@ -103,7 +103,7 @@ class data__accession extends ChadoField {
   /**
    * @see TripalField::validate()
    */
-  public function validate($entity_type, $entity, $field, $items, &$errors) {
+  public function validate($entity_type, $entity, $langcode, $items, &$errors) {
 
     $field_name = $this->field['field_name'];
     $settings = $this->field['settings'];

+ 1 - 1
tripal_chado/includes/TripalFields/obi__organism/obi__organism.inc

@@ -40,7 +40,7 @@ class obi__organism extends ChadoField {
   /**
    * @see TripalField::validate()
    */
-  public function validate($entity_type, $entity, $field, $items, &$errors) {
+  public function validate($entity_type, $entity, $langcode, $items, &$errors) {
 
     $settings = $this->field['settings'];
     $field_name = $this->field['field_name'];

+ 1 - 1
tripal_chado/includes/TripalFields/sbo__database_cross_reference/sbo__database_cross_reference.inc

@@ -207,7 +207,7 @@ class sbo__database_cross_reference extends ChadoField {
   /**
    * @see TripalField::validate()
    */
-  public function validate($entity_type, $entity, $field, $items, &$errors) {
+  public function validate($entity_type, $entity, $langcode, $items, &$errors) {
 
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];

+ 91 - 102
tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship.inc

@@ -743,123 +743,112 @@ class sbo__relationship extends ChadoField {
     $option3 = isset($settings['relationship_types']) && trim($settings['relationship_types']);
     if ($option1 && ($option2 || $option3) == 1 ||
         $option2 && ($option1 || $option3) == 1 ||
-        $option3 && ($option1 || $option2) == 1
-        ) {
-          form_set_error(
-              "instance][settings][relationships",
-              t("Only one option is allowed to limit the relationship types.")
-              );
-          return;
-        }
+        $option3 && ($option1 || $option2) == 1) {
+      form_set_error("instance][settings][relationships", t("Only one option is allowed to limit the relationship types."));
+      return;
+    }
 
-        // For option3, make sure the supplied types are valid cvterms
-        if ($option3) {
-          $rel_types = explode(PHP_EOL, $settings['relationship_types']);
-          foreach($rel_types AS $type) {
-            $type =  trim($type);
-            // Ignore empty lines
-            if ($type == '') {
-              continue;
-            }
-            // Find the matching cvterm
-            $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name";
-            $results = chado_query($sql, array(':name' => $type));
-            $terms = array();
-            while ($obj = $results->fetchObject()) {
-              $terms[] = $obj;
-            }
-            // Don't save the form  if a term can not be found or it matches more than one cvterm
-            $cv = '';
-            if (count($terms) == 0) {
-              // If a term can not be found, maybe the type contains '|', parse it as 'vocabulary|cvterm'
-              if (strpos($type, '|')) {
-                $tmp = explode('|', $type, 2);
-                $type = trim($tmp[1]);
-                $cv = tripal_get_cv(array('name' => trim($tmp[0])));
-                if($cv) {
-                  $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name AND cv_id = :cv_id";
-                  $results = chado_query($sql, array(':name' => $type, ':cv_id' => $cv->cv_id));
-                  while ($obj = $results->fetchObject()) {
-                    $terms[] = $obj;
-                  }
-                }
-                else {
-                  $cv = $tmp[0];
-                }
-              }
-              if (count($terms) != 1) {
-                $message = "The term '@type' can not be found.";
-                $token = array('@type' => $type);
-                if ($cv) {
-                  $message =  "The term '@type' can not be found within the vocabulary '@vocab'.";
-                  $token['@vocab'] = $cv;
-                }
-                form_set_error(
-                    "instance][settings][relationships][relationship_types",
-                    t($message, $token)
-                    );
+    // For option3, make sure the supplied types are valid cvterms
+    if ($option3) {
+      $rel_types = explode(PHP_EOL, $settings['relationship_types']);
+      foreach($rel_types AS $type) {
+        $type =  trim($type);
+        // Ignore empty lines
+        if ($type == '') {
+          continue;
+        }
+        // Find the matching cvterm
+        $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name";
+        $results = chado_query($sql, array(':name' => $type));
+        $terms = array();
+        while ($obj = $results->fetchObject()) {
+          $terms[] = $obj;
+        }
+        // Don't save the form  if a term can not be found or it matches more than one cvterm
+        $cv = '';
+        if (count($terms) == 0) {
+          // If a term can not be found, maybe the type contains '|', parse it as 'vocabulary|cvterm'
+          if (strpos($type, '|')) {
+            $tmp = explode('|', $type, 2);
+            $type = trim($tmp[1]);
+            $cv = tripal_get_cv(array('name' => trim($tmp[0])));
+            if($cv) {
+              $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name AND cv_id = :cv_id";
+              $results = chado_query($sql, array(':name' => $type, ':cv_id' => $cv->cv_id));
+              while ($obj = $results->fetchObject()) {
+                $terms[] = $obj;
               }
             }
-            else if (count($terms) > 1) {
-              // If a type matches more than one term, parse it as 'vocabulary|cvterm' and try again
-              if (strpos($type, '|')) {
-                $tmp = explode('|', $type, 2);
-                $type = trim($tmp[1]);
-                $cv = tripal_get_cv(array('name' => trim($tmp[0])));
-                if ($cv) {
-                  $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name AND cv_id = :cv_id";
-                  $results = chado_query($sql, array(':name' => $type, ':cv_id' => $cv->cv_id));
-                  while ($obj = $results->fetchObject()) {
-                    $terms[] = $obj;
-                  }
-                }
-              }
-              if(count($terms) != 1) {
-                form_set_error(
-                    "instance][settings][relationships][relationship_types",
-                    t("The term '@type' matches more than one term. Please specify its vocabulary in
-                  the format of 'vocabulary|@type'.", array('@type' => $type))
-                    );
-              }
+            else {
+              $cv = $tmp[0];
+            }
+          }
+          if (count($terms) != 1) {
+            $message = "The term '@type' can not be found.";
+            $token = array('@type' => $type);
+            if ($cv) {
+              $message =  "The term '@type' can not be found within the vocabulary '@vocab'.";
+              $token['@vocab'] = $cv;
             }
+            form_set_error("instance][settings][relationships][relationship_types",
+                t($message, $token));
           }
         }
-
-        // For option2: Make sure the parent term is a valid cvterm
-        if ($option2) {
-          $cv_id = $settings['option2_vocab'];
-          $supertype = $settings['option2_parent'];
-          $term = tripal_get_cvterm(array(
-            'name' => trim($supertype),
-            'cv_id' => $cv_id,
-          ));
-          // Tripal cv autocomplete also allow cvterm synonyms, if the parent term doesn't match
-          // a cvterm, try cvtermsynonym
-          if (!$term) {
-            $synonym = tripal_get_cvterm(
-                array(
-                  'synonym' => array(
-                    'name' => trim($supertype),
-                  )
-                )
-                );
-            if ($synonym && $synonym->cv_id->cv_id == $cv_id) {
-              $term = $synonym;
+        else if (count($terms) > 1) {
+          // If a type matches more than one term, parse it as 'vocabulary|cvterm' and try again
+          if (strpos($type, '|')) {
+            $tmp = explode('|', $type, 2);
+            $type = trim($tmp[1]);
+            $cv = tripal_get_cv(array('name' => trim($tmp[0])));
+            if ($cv) {
+              $sql = "SELECT cvterm_id FROM {cvterm} WHERE name = :name AND cv_id = :cv_id";
+              $results = chado_query($sql, array(':name' => $type, ':cv_id' => $cv->cv_id));
+              while ($obj = $results->fetchObject()) {
+                $terms[] = $obj;
+              }
             }
           }
-          if (!isset($term->cvterm_id)) {
-            form_set_error(
-                "instance][settings][relationships][option2_parent",
-                t("The term '@type' is not a valid term for the vocabulary selected.", array('@type' => $supertype))
-                );
+          if(count($terms) != 1) {
+            form_set_error("instance][settings][relationships][relationship_types",
+              t("The term '@type' matches more than one term. Please specify its vocabulary in the format of 'vocabulary|@type'.", array('@type' => $type)));
           }
         }
+      }
+    }
+
+    // For option2: Make sure the parent term is a valid cvterm
+    if ($option2) {
+      $cv_id = $settings['option2_vocab'];
+      $supertype = $settings['option2_parent'];
+      $term = tripal_get_cvterm(array(
+        'name' => trim($supertype),
+        'cv_id' => $cv_id,
+      ));
+      // Tripal cv autocomplete also allow cvterm synonyms, if the parent term doesn't match
+      // a cvterm, try cvtermsynonym
+      if (!$term) {
+        $synonym = tripal_get_cvterm(
+            array(
+              'synonym' => array(
+                'name' => trim($supertype),
+              )
+            )
+            );
+        if ($synonym && $synonym->cv_id->cv_id == $cv_id) {
+          $term = $synonym;
+        }
+      }
+      if (!isset($term->cvterm_id)) {
+        form_set_error("instance][settings][relationships][option2_parent",
+            t("The term '@type' is not a valid term for the vocabulary selected.", array('@type' => $supertype)));
+      }
+    }
   }
 
   /**
    * @see TripalField::validate()
    */
-  public function validate($entity_type, $entity, $field, $items, &$errors) {
+  public function validate($entity_type, $entity, $langcode, $items, &$errors) {
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];

+ 57 - 21
tripal_chado/includes/TripalFields/sio__annotation/sio__annotation.inc

@@ -49,6 +49,30 @@ class sio__annotation extends ChadoField {
   // and field_create_instance().
   public static $no_ui = FALSE;
 
+
+  public function validate($entity_type, $entity, $langcode, $items, &$errors) {
+
+    $field_name = $this->field['field_name'];
+
+    foreach ($items as $delta => $item) {
+      // Get the term that matches.
+      $cvterm_name = $item['cvterm_name'];
+      $cv_id = $item['cv_id'];
+      if($cvterm_name and $cv_id) {
+        $cvterm = chado_generate_var('cvterm', array(
+          'cv_id' => $cv_id,
+          'name' => $cvterm_name,
+        ));
+        if (!$cvterm) {
+          $errors[$field_name][$langcode][$delta][] = array(
+            'message' =>  t("Cannot find a term that matches the term name and vocabulary."),
+            'error' => 'cvterm_name'
+          );
+        }
+      }
+    }
+  }
+
   /**
    *
    * @see TripalField::load()
@@ -60,43 +84,49 @@ class sio__annotation extends ChadoField {
     $field_column = $this->instance['settings']['chado_column'];
     $base_table = $this->instance['settings']['base_table'];
 
-    $vocabulary = tripal_get_chado_semweb_term('db', 'name');
-    $accession = tripal_get_chado_semweb_term('db', 'accession');
-    $definition = tripal_get_chado_semweb_term('cvterm', 'definition');
-
     // Get the FK that links to the base record.
     $schema = chado_get_schema($field_table);
     $pkey = $schema['primary key'][0];
     $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
     $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
 
+    $vocabulary = tripal_get_chado_semweb_term('cvterm', 'cv_id');
+    $accession = tripal_get_chado_semweb_term('dbxref', 'accession');
+    $definition = tripal_get_chado_semweb_term('cvterm', 'definition');
+    if (array_key_exists('is_not', $schema['fields'])) {
+      $negation = tripal_get_chado_semweb_term($field_table, 'is_not');
+    }
+
     // Set some defaults for the empty record.
     $chado_record = $entity->chado_record;
     $entity->{$field_name}['und'][0] = array(
       'value' => '',
       'chado-' . $field_table . '__' . $pkey => '',
       'chado-' . $field_table . '__' . $fkey_lcolumn => $chado_record->$fkey_rcolumn,
-      'chado-' . $field_table . '__' . 'cvterm_id' => '',
-      // The pub column is present in the cell_line_cvterm, feature_cvterm,
-      // library_cvterm, phenotype_comparision_cvterm, phenotype_cvterm,
-      // stock_cvterm, and stock_relationship_cvterm.
-      'chado-' . $field_table . '__' . 'pub_id' => '',
-      // The is_not column is present in feature_cvterm and stock_cvterm tables.
-      'chado-' . $field_table . '__' . 'is_not' => '',
-      // The rank column is present in the cell_line_cvterm, expression_cvterm,
-      // feature_cvterm, phenotype_comparision_cvterm, phenotype_cvterm,
-      // and stock_cvterm tables.
-      'chado-' . $field_table . '__' . 'rank' => '',
+      'chado-' . $field_table . '__cvterm_id' => '',
     );
+    if (array_key_exists('is_not', $schema['fields'])) {
+      $entity->{$field_name}['und'][0]['chado-' . $field_table . '__is_not'] = '';
+    }
+    if (array_key_exists('rank', $schema['fields'])) {
+      $entity->{$field_name}['und'][0]['chado-' . $field_table . '__rank'] = '';
+    }
+    if (array_key_exists('pub_id', $schema['fields'])) {
+      $entity->{$field_name}['und'][0]['chado-' . $field_table . '__pub_id'] = '';
+    }
 
     // Get the annotations associated with this base record for this fields type.
     $columns = array('*');
     $match = array(
       $fkey_lcolumn => $chado_record->$fkey_rcolumn,
     );
+    $order_by = array($pkey => 'ASC');
+    if (array_key_exists('rank', $schema['fields'])) {
+      $order_by = array('rank' => 'ASC');
+    }
     $options = array(
       'return_array' => TRUE,
-      'order_by' => array('rank' => 'ASC')
+      'order_by' => $order_by
     );
     $fcvterms = chado_select_record($field_table, $columns, $match, $options);
     for ($i = 0; $i < count($fcvterms); $i++) {
@@ -106,16 +136,22 @@ class sio__annotation extends ChadoField {
         'value' => array(
           $vocabulary => $cvterm->dbxref_id->db_id->name,
           $accession => $cvterm->dbxref_id->accession,
-          $definition => $cvterm->cvterm_id->name
+          $definition => $cvterm->name
         ),
         'chado-' . $field_table . '__' . $pkey => $linker->$pkey,
         'chado-' . $field_table . '__' . $fkey_lcolumn => $linker->$fkey_lcolumn,
         'chado-' . $field_table . '__' . 'cvterm_id' => $linker->cvterm_id,
-        'chado-' . $field_table . '__' . 'pub_id' => property_exists($linker, 'pub_id') ? $linker->pub_id : '',
-        'chado-' . $field_table . '__' . 'is_not' => property_exists($linker, 'is_not') ? $linker->is_not : '',
-        'chado-' . $field_table . '__' . 'rank' => property_exists($linker, 'rank') ? $linker->rank : '',
-        'chado-' . $field_table . '__' . 'cvterm_type_id' => property_exists($linker, 'cvterm_type_id') ? $linker->cvterm_type_id : '',
       );
+      if (array_key_exists('is_not', $schema['fields'])) {
+        $entity->{$field_name}['und'][$i]['value'][$negation] = $linker->is_not;
+        $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__is_not'] = $linker->is_not;
+      }
+      if (array_key_exists('rank', $schema['fields'])) {
+        $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__rank'] = $linker->rank;
+      }
+      if (array_key_exists('pub_id', $schema['fields'])) {
+        $entity->{$field_name}['und'][$i]['chado-' . $field_table . '__pub_id'] = $linker->pub_id;
+      }
     }
   }
 }

+ 31 - 11
tripal_chado/includes/TripalFields/sio__annotation/sio__annotation_formatter.inc

@@ -74,12 +74,26 @@ class sio__annotation_formatter extends ChadoFieldFormatter {
    * @see TripalFieldFormatter::view()
    */
   public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
-    $headers = array('Term', 'Definition', 'Is Not');
+    $headers = array('Term', 'Definition');
     $rows = array();
 
-    dpm($items);
+    $field_table = $this->instance['settings']['chado_table'];
+    $schema = chado_get_schema($field_table);
+
+    if (array_key_exists('is_not', $schema['fields'])) {
+      $headers[] = 'Negates';
+    }
+
+    $vocabulary_term = tripal_get_chado_semweb_term('cvterm', 'cv_id');
+    $accession_term = tripal_get_chado_semweb_term('dbxref', 'accession');
+    $definition_term = tripal_get_chado_semweb_term('cvterm', 'definition');
+    if (array_key_exists('is_not', $schema['fields'])) {
+      $negation_term = tripal_get_chado_semweb_term($field_table, 'is_not');
+    }
+
     $chado_table = $this->instance['settings']['chado_table'];
     foreach ($items as $delta => $item) {
+
       if ($item['chado-' . $chado_table . '__cvterm_id']) {
         $cvterm = chado_generate_var('cvterm', array('cvterm_id' => $item['chado-' . $chado_table . '__cvterm_id']));
         $dbxref = $cvterm->dbxref_id;
@@ -90,18 +104,24 @@ class sio__annotation_formatter extends ChadoFieldFormatter {
           $accession = l($accession, tripal_get_dbxref_url($dbxref), array('attributes' => array('target' => '_blank')));
         }
 
-        $rows[] = array(
-          $accession,
-          $cvterm->definition,
-          $item['chado-' . $chado_table . '__is_not'] ? 'Yes' : '',
+        $row = array(
+          $item['value'][$vocabulary_term] . ':' . $item['value'][$accession_term],
+          $item['value'][$definition_term],
         );
+
+        if (array_key_exists('is_not', $schema['fields'])) {
+          $row[] = $item['value'][$negation_term];
+        }
+
+        $rows[] = $row;
       }
     }
 
-    // the $table array contains the headers and rows array as well as other
-    // options for controlling the display of the table.  Additional
-    // documentation can be found here:
-    // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
+    // Theme the results in a talbe.
+    $caption = 'This record is associated with the following annotations.';
+    if (array_key_exists('is_not', $schema['fields'])) {
+      $caption .= 'The "Negates" column indicates if the term does NOT apply.';
+    }
     $table = array(
       'header' => $headers,
       'rows' => $rows,
@@ -109,7 +129,7 @@ class sio__annotation_formatter extends ChadoFieldFormatter {
         'id' => "$chado_table-table-terms",
         'class' => 'tripal-data-table'
       ),
-      'caption' => 'This record is associated with the following annotations:',
+      'caption' => $caption,
       'sticky' => FALSE,
       'colgroups' => array(),
       'empty' => 'There are no annotations of this type',

+ 198 - 100
tripal_chado/includes/TripalFields/sio__annotation/sio__annotation_widget.inc

@@ -13,69 +13,99 @@ class sio__annotation_widget extends ChadoFieldWidget {
    */
   public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
     parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
-    $field_name = $this->field['field_name'];
-
-    $matches = array();
-    preg_match('/(.*?)__(\d+)/', $field_name, $matches);
-    // If the field name is not properly formatted then we can't tell what
-    // table and type this is.  So just return.
-    if (count($matches) != 3) {
-      return $widget;
-    }
-    $table_name = $matches[1];
-    $cv_id = $matches[2];
 
-    // Get the FK column that links to the base table.
-    $chado_table = $this->instance['settings']['chado_table'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
     $base_table = $this->instance['settings']['base_table'];
-    $schema = chado_get_schema($chado_table);
+
+    // Get the FK that links to the base record.
+    $schema = chado_get_schema($field_table);
     $pkey = $schema['primary key'][0];
-    $fkeys = array_values($schema['foreign keys'][$base_table]['columns']);
-    $fkey = $fkeys[0];
+    $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
+    $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
+
+    $vocabulary = tripal_get_chado_semweb_term('cvterm', 'cv_id');
+    $accession = tripal_get_chado_semweb_term('dbxref', 'accession');
+    $definition = tripal_get_chado_semweb_term('cvterm', 'definition');
+    if (array_key_exists('is_not', $schema['fields'])) {
+      $negation = tripal_get_chado_semweb_term($field_table, 'is_not');
+    }
 
     // Get the field defaults.
     $record_id = '';
-    $fkey_value = $element['#entity']->chado_record_id;
-    $cvterm_name = '';
+    $fk_value = '';
     $cvterm_id = '';
     $pub_id = '';
-    $uname = '';
-    $is_not = '';
+    $is_not = FALSE;
+    $rank = $delta;
+    $cvterm_name = '';
+    $cv_id = '';
     $cvterm = NULL;
+    $pub_name = '';
 
     // If the field already has a value then it will come through the $items
     // array.  This happens when editing an existing record.
     if (array_key_exists($delta, $items)) {
-      $record_id = $items[$delta]['value'];
-      $cvterm_name = $items[$delta]['cvterm__name'];
-      $pub_id =$items[$delta]['chado-' . $table_name . '__pub_id'];
-      if ($pub_id && $pub_id != 1) {
-        $pub = chado_generate_var('pub', array('pub_id' => $pub_id));
-        $uname = $pub->uniquename;
+      // Check for element values that correspond to fields in the Chado table.
+      $record_id = tripal_get_field_item_keyval($items, $delta, 'chado-' . $field_table . '__' . $pkey, $record_id);
+      $fk_value = tripal_get_field_item_keyval($items, $delta, 'chado-' . $field_table . '__' . $fkey_lcolumn, $fk_value);
+      $cvterm_id = tripal_get_field_item_keyval($items, $delta, 'chado-' . $field_table . '__cvterm_id', $cvterm_id);
+
+      if (array_key_exists('pub_id', $schema['fields'])) {
+        $pub_name = tripal_get_field_item_keyval($items, $delta, 'pub', $pub_name);
+        $pub_id = tripal_get_field_item_keyval($items, $delta, 'chado-' . $field_table . '__pub_id', $pub_id);
+      }
+      if (array_key_exists('rank', $schema['fields'])) {
+        $rank = tripal_get_field_item_keyval($items, $delta, 'chado-' . $field_table . '__rank', $rank);
+      }
+      if (array_key_exists('is_not', $schema['fields'])) {
+        $is_not = tripal_get_field_item_keyval($items, $delta, 'chado-' . $field_table . '__is_not', $is_not);
+      }
+
+      if ($cvterm_id) {
+        $cvterm = chado_generate_var('cvterm', array('cvterm_id' => $cvterm_id));
+        $cv_id = $cvterm->cv_id->cv_id;
+        $cvterm_name = $cvterm->name;
       }
-      $is_not = $items[$delta]['chado-' . $table_name . '__is_not'];
-      $cvterm_id = $items[$delta]['chado-' . $table_name . '__cvterm_id'];
     }
 
     // Check $form_state['values'] to see if an AJAX call set the values.
-    if (array_key_exists('values', $form_state) and array_key_exists($delta, $form_state['values'])) {
-      // See example in chado_linker_contact.inc
-      //       $record_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name);
-      //       $fkey_value = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__' . $fkey);
-      //       $is_not = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__is_not');
-      //       $cvterm_name = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '--cvterm__name');
-    }
+    if ((array_key_exists('values', $form_state) and array_key_exists($field_name, $form_state['values'])) or
+        (array_key_exists('input', $form_state) and array_key_exists($field_name, $form_state['input']))) {
 
-    if ($cvterm_name) {
-      $cvterm = chado_generate_var('cvterm', array('cv_id' => $cv_id, 'name' => $cvterm_name));
-    }
+      $vtype = 'input';
+      if (array_key_exists('values', $form_state)) {
+        $vtype = 'values';
+      }
+
+      $record_id = $form_state[$vtype][$field_name]['und'][$delta]['chado-' . $field_table . '__' . $pkey];
+      $fk_value = $form_state[$vtype][$field_name]['und'][$delta]['chado-' . $field_table . '__' . $fkey_lcolumn];
+      $cvterm_id = $form_state[$vtype][$field_name]['und'][$delta]['chado-' . $field_table . '__cvterm_id'];
 
-    $schema = chado_get_schema('cvterm');
-    $options = tripal_get_cv_select_options();
+      if (array_key_exists('pub_id', $schema['fields'])) {
+        $pub_name = $form_state[$vtype][$field_name]['und'][$delta]['pub'];
+        $pub_id = $form_state[$vtype][$field_name]['und'][$delta]['chado-' . $field_table . '__pub_id'];
+      }
+      if (array_key_exists('rank', $schema['fields'])) {
+        $rank = $form_state[$vtype][$field_name]['und'][$delta]['chado-' . $field_table . '__rank'];
+      }
+      if (array_key_exists('is_not', $schema['fields'])) {
+        $is_not = $form_state[$vtype][$field_name]['und'][$delta]['chado-' . $field_table . '__is_not'];
+      }
+      $cvterm_name = $form_state[$vtype][$field_name]['und'][$delta]['cvterm_name'];
+      $cv_id = $form_state[$vtype][$field_name]['und'][$delta]['cv_id'];
+      $cvterm = chado_generate_var('cvterm', array(
+        'cv_id' => $cv_id,
+        'name' => $cvterm_name,
+      ));
+      if (!$cvterm) {
+        $cvterm_name = '';
+      }
+    }
 
-    $widget['#table_name'] = $chado_table;
-    $widget['#fkey_field'] = $fkey;
-    $widget['#prefix'] =  "<span id='$table_name-$delta'>";
+    $widget['#prefix'] =  "<span id='$field_name-sio--annotation-$delta'>";
     $widget['#suffix'] =  "</span>";
 
     $widget['value'] = array(
@@ -83,63 +113,68 @@ class sio__annotation_widget extends ChadoFieldWidget {
       '#value' => key_exists($delta, $items) ? $items[$delta]['value'] : '',
     );
 
-    $widget['chado-' . $table_name . '__' . $pkey] = array(
+    $widget['chado-' . $field_table . '__' . $pkey] = array(
       '#type' => 'value',
       '#default_value' => $record_id,
     );
-    $widget['cv__cv_id'] = array(
+    $widget['chado-' . $field_table . '__cvterm_id'] = array(
       '#type' => 'value',
-      '#default_value' => $cv_id,
+      '#default_value' => $cvterm_id,
     );
-    $widget['chado-' . $table_name . '__cvterm_id'] = array(
+    $widget['chado-' . $field_table . '__' . $fkey_lcolumn] = array(
       '#type' => 'value',
-      '#default_value' => $cvterm ? $cvterm->cvterm_id : '',
-    );
-    $widget['chado-' . $table_name . '__' . $fkey] = array(
-      '#type' => 'value',
-      '#default_value' => $fkey_value,
+      '#default_value' => $fk_value,
     );
 
-    $widget['cvterm__name'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Term Name'),
-      '#default_value' => $cvterm_name,
+    $cvs = tripal_get_cv_select_options();
+    $widget['cv_id'] = array(
+      '#type' => 'select',
+      '#title' => t('Vocabulary'),
+      '#options' => $cvs,
+      '#default_value' => $cv_id,
       '#required' => $element['#required'],
-      '#maxlength' => array_key_exists('length', $schema['fields']['name']) ? $schema['fields']['name']['length'] : 255,
-      '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/cvterm/' . $cv_id,
-      '#size' => 30
-    );
-
-    $widget['pub'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Publication'),
-      '#default_value' => $uname,
-      '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/pub',
+      '#attributes' => array('style' => 'width: 200px;'),
       '#ajax' => array(
-        'callback' => "schema__publication_widget_form_ajax_callback",
-        'wrapper' => "$table_name-$delta",
+        'callback' => "sio__annotation_widget_form_ajax_callback",
+        'wrapper' => "$field_name-sio--annotation-$delta",
         'effect' => 'fade',
         'method' => 'replace'
       ),
-      '#maxlength' => 100000,
     );
-
-    $widget['chado-' . $table_name . '__pub_id'] = array(
-      '#type' => 'value',
-      '#default_value' => $pub_id ? $pub_id : 1,
+    $cv_schema = chado_get_schema('cvterm');
+    $widget['cvterm_name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Term Name'),
+      '#default_value' => $cvterm_name,
+      '#maxlength' => array_key_exists('length', $cv_schema['fields']['name']) ? $cv_schema['fields']['name']['length'] : 255,
+      '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/cvterm/' . $cv_id,
+      '#disabled' => $cv_id ? FALSE : TRUE,
     );
 
-    $widget['chado-' . $table_name . '__is_not'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Is Not'),
-      '#default_value' => $is_not,
-      '#required' => $element['#required'],
-    );
+    if (array_key_exists('pub_id', $schema['fields'])) {
+      $widget['pub'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Publication'),
+        '#default_value' => $pub_name,
+        '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/pub',
+        '#maxlength' => 100000,
+        '#disabled' => $cv_id ? FALSE : TRUE,
+      );
+      $widget['chado-' . $field_table . '__pub_id'] = array(
+        '#type' => 'value',
+        '#default_value' => $pub_id ? $pub_id : '',
+      );
+    }
 
-    $widget['cvterm__definition'] = array(
-      '#type' => 'item',
-      '#markup' => '',
-    );
+    if (array_key_exists('is_not', $schema['fields'])) {
+      $widget['chado-' . $field_table . '__is_not'] = array(
+        '#type' => 'checkbox',
+        '#title' => t('Negate this term (NOT)'),
+        '#default_value' => $is_not,
+        '#required' => $element['#required'],
+        '#disabled' => $cv_id ? FALSE : TRUE,
+      );
+    }
   }
 
   /**
@@ -148,29 +183,92 @@ class sio__annotation_widget extends ChadoFieldWidget {
    */
   public function submit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
     $field_name = $this->field['field_name'];
-    $table_name = $this->instance['settings']['chado_table'];
-    $schema = chado_get_schema($table_name);
-    $pkey = $schema['primary key'][0];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
     $base_table = $this->instance['settings']['base_table'];
-    $lfkey_field = key($schema['foreign keys'][$base_table]['columns']);
-    $rfkey_field = $schema['foreign keys'][$base_table]['columns'][$lfkey_field];
 
+    // Get the FK that links to the base record.
+    $schema = chado_get_schema($field_table);
+    $pkey = $schema['primary key'][0];
+    $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
+    $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];
 
-    // If the form ID is field_ui_field_edit_form, then the user is editing the
-    // field's values in the manage fields form of Drupal.  We don't want
-    // to validate it as if it were being used in a data entry form.
-    if ($form_state['build_info']['form_id'] =='field_ui_field_edit_form') {
-      return;
+    $vocabulary = tripal_get_chado_semweb_term('cvterm', 'cv_id');
+    $accession = tripal_get_chado_semweb_term('dbxref', 'accession');
+    $definition = tripal_get_chado_semweb_term('cvterm', 'definition');
+    if (array_key_exists('is_not', $schema['fields'])) {
+      $negation = tripal_get_chado_semweb_term($field_table, 'is_not');
     }
 
-    // If the user provided a cv_id and a name then we want to set the
-    // foreign key value to be the chado_record_idd
-    $cvterm_name = isset($form_state['values'][$field_name][$langcode][$delta]['cvterm__name']) ? $form_state['values'][$field_name][$langcode][$delta]['cvterm__name'] : '';
 
-    if (!$cvterm_name) {
-      $form_state['values'][$field_name][$langcode][$delta]['chado-' . $table_name . '__cvterm_id'] = '';
-      $form_state['values'][$field_name][$langcode][$delta]['chado-' . $table_name . '__' . $lfkey_field] = '';
-      $form_state['values'][$field_name][$langcode][$delta]['chado-' . $table_name . '__pub_id'] = '';
+    $record_id = $form_state['values'][$field_name]['und'][$delta]['chado-' . $field_table . '__' . $pkey];
+    $fk_value = $form_state['values'][$field_name]['und'][$delta]['chado-' . $field_table . '__' . $fkey_lcolumn];
+
+
+    // If a publication ID was provided then make sure the form_state
+    // value for the pub_id is set correctly.
+    if (array_key_exists('pub_id', $schema['fields'])) {
+      $pub_name = $form_state['values'][$field_name]['und'][$delta]['pub'];
+      if ($pub_name) {
+        $pub = chado_generate_var('pub', array('uniquename' => $pub_name));
+        if ($pub) {
+          $form_state['values'][$field_name][$langcode][$delta]['chado-' . $table_name . '__pub_id'] = $pub->pub_id;
+        }
+      }
+    }
+
+    // Make sure the rank is set.
+    if (array_key_exists('rank', $schema['fields'])) {
+      $rank = $form_state['values'][$field_name]['und'][$delta]['_weight'];
+      $form_state['values'][$field_name]['und'][$delta]['chado-' . $field_table . '__rank'] = $rank;
+    }
+
+    // Get the term that matches.
+    $cvterm_name = $form_state['values'][$field_name]['und'][$delta]['cvterm_name'];
+    $cv_id = $form_state['values'][$field_name]['und'][$delta]['cv_id'];
+    $cvterm = chado_generate_var('cvterm', array(
+      'cv_id' => $cv_id,
+      'name' => $cvterm_name,
+    ));
+    if ($cvterm) {
+      $form_state['values'][$field_name]['und'][$delta]['cvterm_name'] = '';
+      $form_state['values'][$field_name]['und'][$delta]['chado-' . $field_table . '__cvterm_id'] = $cvterm->cvterm_id;
     }
   }
+
+  /**
+   * @see TripalFieldWidget::theme()
+   */
+  public function theme($element) {
+    $field_table = $this->instance['settings']['chado_table'];
+    $layout = "
+      <div class=\"sio--annotation-widget\">
+        <div class=\"sio--annotation-item\">" .
+          drupal_render($element['cv_id']) . "
+        </div>
+        <div class=\"sio--annotation-item\">" .
+          drupal_render($element['cvterm_name']) . "
+        </div>
+        <div class=\"sio--annotation-item\">" .
+          drupal_render($element['pub']) . "
+        </div>
+        <div class=\"sio--annotation-item\">" .
+          drupal_render($element['chado-' . $field_table . '__is_not']) . "
+        </div>
+      </div>
+    ";
+
+    return $layout;
+  }
+}
+
+/**
+ * An Ajax callback for the tripal_chado_admin_publish_form..
+ */
+function sio__annotation_widget_form_ajax_callback($form, $form_state) {
+  $field_name = $form_state['triggering_element']['#parents'][0];
+  $delta = $form_state['triggering_element']['#parents'][2];
+
+  return $form[$field_name]['und'][$delta];
 }

+ 1 - 1
tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary.inc

@@ -38,7 +38,7 @@ class sio__vocabulary extends ChadoField {
   /**
    * @see TripalField::validate()
    */
-  public function validate($entity_type, $entity, $field, $items, &$errors) {
+  public function validate($entity_type, $entity, $langcode, $items, &$errors) {
 
     $settings = $this->field['settings'];
     $field_name = $this->field['field_name'];

+ 1 - 1
tripal_chado/includes/tripal_chado.field_storage.inc

@@ -43,7 +43,7 @@ function tripal_chado_field_storage_write($entity_type, $entity, $op, $fields) {
 
   // Convert the fields into a key/value list of fields and their values.
   $field_vals = tripal_chado_field_storage_write_merge_fields($fields, $entity_type, $entity);
-dpm($field_vals);
+
   // First, write the record for the base table.  If we have a record id then
   // this is an update and we need to set the primary key.  If not, then this
   // is an insert and we need to set the type_id if the table supports it.

+ 1 - 0
tripal_chado/theme/css/tripal_chado.css

@@ -2,6 +2,7 @@
 
 .synonym-widget-item,
 .primary-dbxref-widget-item,
+.sio--annotation-item,
 .secondary-dbxref-widget-item,
 .kvproperty-adder-widget-item,
 .chado-linker--relationship-widget-item,

+ 5 - 3
tripal_ws/includes/TripalWebService/TripalEntityService_v0_1.inc

@@ -327,10 +327,12 @@ class TripalEntityService_v0_1 extends TripalWebService {
     if (is_array($value)) {
       $temp = array();
       foreach ($value as $k => $v) {
+
         // exclude fields that have no values so we can hide them
-        if (empty($v) and $hide_fields == 'hide') {
+        if (!isset($v) and $hide_fields == 'hide') {
           continue;
         }
+
         $matches = array();
         if (preg_match('/^(.+):(.+)$/', $k, $matches)) {
           $vocabulary = $matches[1];
@@ -342,7 +344,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
             $temp[$key_adj] = $this->sanitizeFieldKeys($v, $bundle, $service_path);
           }
           else {
-            $temp[$key_adj] = $v !== "" ? $v : NULL;
+            $temp[$key_adj] = $v;
           }
           $this->resource->addContextItem($key_adj, $term['url']);
 
@@ -360,7 +362,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
 
     }
     else {
-      $new_value = $value !== "" ? $value : NULL;
+      $new_value = $value;
     }
 
     return $new_value;