Browse Source

Updated web services to support display of vocabularies and terms. Working on field formatt settings form for organism_id

Stephen Ficklin 9 years ago
parent
commit
63643cc426

+ 152 - 9
tripal/api/tripal.entities.api.inc

@@ -20,7 +20,7 @@ function tripal_load_term_entity($values) {
 
   if ($namespace and $accession) {
     $query = db_select('tripal_term', 'tt');
-    $query->join('tripal_vocab' ,'tv', 'tv.id = tt.vocab_id');
+    $query->join('tripal_vocab', 'tv', 'tv.id = tt.vocab_id');
     $query->fields('tt', array('id'))
       ->fields('tv', array('namespace'))
       ->condition('tv.namespace', $namespace)
@@ -279,6 +279,7 @@ function tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $b
   );
   field_create_instance($field_instance);
 }
+
 /**
  * Allows a module to make changes to an entity object after creation.
  *
@@ -291,24 +292,127 @@ function tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $b
 function hook_entity_create(&$entity, $entity_type) {
 
 }
+
+
 /**
- * Allows a module to add fields to a bundle.
+ * Adds fields to a bundle type.
  *
- * This function is called after the bundle is created and allows any module
- * to add fields to it.
+ * When a new bundle (Tripal content type) is created, the tripal module
+ * allows any other module the implements this hook to add fields too it. This
+ * hook is called automatically.
  *
  * @param $entity_type
- *   The entity type (e.g. TripalEntity).
+ *   The type of entity (e.g. 'TripalEntity')
  * @param $bundle
- *   A TripalBundle object.
+ *   An instance of a TripalBundle object.  This is the bundle to which
+ *   the fields will be added.
  * @param $term
- *   A TripalTerm object.
+ *   An instance of a TripalTerm object. Each TripalBundle is associated with
+ *   a controlled vocabulary term. This is the term object for the bundle.
  *
  * @return
- *   TRUE on success, FALSE on failure.
+ *   There is no return value.
  */
 function hook_add_bundle_fields($entity_type, $bundle, $term) {
 
+  //
+  // The example code below is derived from the tripal_chado modules and
+  // adds a 'synonym' field to the bundle.
+  //
+
+  $bundle_name = $bundle->name;
+
+  // This array will hold details that map the bundle to tables in Chado.
+  $bundle_data = array();
+
+  // Get the cvterm that corresponds to this TripalTerm object.
+  $vocab = entity_load('TripalVocab', array($term->vocab_id));
+  $vocab = reset($vocab);
+  $match = array(
+    'dbxref_id' => array(
+      'db_id' => array(
+        'name' => $vocab->namespace,
+      ),
+      'accession' => $term->accession
+    ),
+  );
+  $cvterm = chado_generate_var('cvterm', $match);
+
+
+  // Get the default table that this term maps to.
+  $default = db_select('tripal_cv_defaults', 't')
+  ->fields('t')
+  ->condition('cv_id', $cvterm->cv_id->cv_id)
+  ->execute()
+  ->fetchObject();
+  if ($default) {
+    $bundle_data = array(
+      'cv_id' => $cvterm->cv_id->cv_id,
+      'cvterm_id' => $cvterm->cvterm_id,
+      'data_table' => $default->table_name,
+      'type_table' => $default->table_name,
+      'field' =>  $default->field_name,
+    );
+  }
+  else {
+    return;
+  }
+
+  // Formulate the name of the synonym table.
+  $syn_table = $bundle_data['data_table'] . '_synonym';
+
+  // Don't add a field to this bundle if
+  if (!chado_table_exists($syn_table)) {
+    return;
+  }
+
+  $field_name = $syn_table;
+  $schema = chado_get_schema($syn_table);
+  $pkey = $schema['primary key'][0];
+
+
+  // Tripal wants to map fields to a controlled vocabulary terms
+  // (e.g SO:0000704 for a 'gene').  This is not required, but is highly
+  // recommended to support mashups of data via web services.
+  $semantic_web = array(
+    // The type is the term from a vocabulary that desribes this field..
+    'type' => '',
+    // The namepsace for the vocabulary (e.g. 'foaf').
+    'ns' => '',
+    // The URL for the namespace.  It must be that the type can be
+    // appended to the URL.
+    'nsurl' => '',
+  );
+
+  // The Tripal Chado module needs to know what Chado table and field
+  // this field maps to, as well as the base table that it maps to
+  // if this field will map to a record in a linking table.
+  $field_settings = array(
+    // The Chado table that this field maps to.
+    'chado_table' => $syn_table,
+    // The column in the chado table that this field maps to.
+    'chado_column' => $pkey,
+    // The base table that this field is connected to.
+    'base_table' => $base_table,
+    'semantic_web' => $semantic_web,
+  );
+
+  // Finally set the field values.
+  $field_info = array(
+    'field_type' => 'synonym',
+    'widget_type' => 'tripal_fields_synonym_widget',
+    'widget_settings' => array('display_label' => 1),
+    'description' => '',
+    'label' => 'Synonyms',
+    'is_required' => 0,
+    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+    'storage' => 'field_chado_storage',
+    'field_settings' => $field_settings,
+  );
+
+  // Call the Tripal API function tripal_add_bundle_field to complete the
+  // addition of the field to the bundle.
+  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
 }
 
 /**
@@ -781,7 +885,7 @@ function hook_vocab_import_form_submit($form, &$form_state) {
  *   An array with at least the following keys:
  *     namespace : The namespace of the vocabulary.
  *     accession : The name unique ID of the term.
- *     url_prefix : The URL by which terms (accessions) can be appended.
+ *     url : The URL for the term.
  *     name : The name of the term.
  *     definition : The term's description.
  *   any other keys may be added as desired. Returns NULL if the term
@@ -791,3 +895,42 @@ function hook_vocab_get_term($namespace, $accession) {
   // See the tripal_chado_vocab_get_term() function for an example.
 }
 
+/**
+ * Retrieves full information about a vocabulary term.
+ *
+ * Vocabularies are stored in a database backend.  Tripal has no requirements
+ * for how terms are stored.  By default, the tripal_chado modules provides
+ * storage for vocabularies and terms. This function will call the
+ * hook_vocab_get_term() function for the database backend that is housing the
+ * vocabularies and allow it to return the details about the term.
+ *
+ * @param $namespace
+ *   The namespace of the vocabulary in which the term is found.
+ * @param $accession
+ *   The unique identifier (accession) for this term.
+ *
+ * @return
+ *   An array with at least the following keys:
+ *     namespace : The namespace of the vocabulary.
+ *     accession : The name unique ID of the term.
+ *     url : The URL for the term.
+ *     name : The name of the term.
+ *     definition : The term's description.
+ *   any other keys may be added as desired. Returns NULL if the term
+ *   cannot be found.
+ */
+function tripal_get_term_details($namespace, $accession) {
+  // TODO: we need some sort of administrative interface that lets the user
+  // switch to the desired vocabulary type. For now, we'll just use the
+  // first one in the list.
+  $stores = module_invoke_all('vocab_storage_info');
+  if (is_array($stores) and count($stores) > 0) {
+    $keys = array_keys($stores);
+    $module = $stores[$keys[0]]['module'];
+    $function = $module . '_vocab_get_term';
+    if (function_exists($function)) {
+      return $function($vocab->namespace, $this->accession);
+    }
+  }
+}
+

+ 1 - 1
tripal/includes/TripalBundleUIController.inc

@@ -443,7 +443,7 @@ function tripal_admin_add_type_form_submit($form, &$form_state) {
       }
     }
     else {
-      drupal_set_message('This type already exists.', 'warning');
+      drupal_set_message("The term '$accession' already exists as a content type.", 'warning');
     }
   }
 }

+ 2 - 2
tripal/includes/TripalTerm.inc

@@ -13,7 +13,7 @@ class TripalTerm extends Entity {
 
     // Get the term description from the storage backend
     $this->definition = NULL;
-    $this->urlprefix = NULL;
+    $this->url = NULL;
 
     // TODO: we need some sort of administrative interface that lets the user
     // switch to the desired vocabulary type. For now, we'll just use the
@@ -28,7 +28,7 @@ class TripalTerm extends Entity {
         $this->details = $term_details;
         if ($term_details and $term_details['definition']) {
           $this->definition = $term_details['definition'];
-          $this->urlprefix = $term_details['urlprefix'];
+          $this->url = $term_details['url'];
         }
       }
     }

+ 76 - 22
tripal_chado/includes/fields/organism_id.inc

@@ -73,43 +73,97 @@ function tripal_chado_organism_select_widget_validate($element, &$form_state) {
   }
 }
 
-function organism_id_field_formatter_settings_summary($field, $instance, $view_mode) {
-  $display = $instance['display'][$view_mode];
-  $settings = $display['settings'];
-
-  $summary = '';
-
-  if ($display['type'] == 'text_trimmed' || $display['type'] == 'text_summary_or_trimmed') {
-    $summary = t('Length: @chars chars', array('@chars' => $settings['trim_length']));
-  }
-
-  return $summary;
-}
 /**
- * Implements hook_field_formatter_settings_form()
+ * Provides a settings form for the formatter.
+ *
+ * This function is equiavlent to the hook_field_formatter_settings_form()
+ * hook.
  *
  * @param $field
+ *   The field structure being configured.
  * @param $instance
+ *   The instance structure being configured.
  * @param $view_mode
+ *   The view mode being configured.
  * @param $form
+ *   The (entire) configuration form array, which will usually have no use here.
  * @param $form_state
+ *   The form state of the (entire) configuration form.
  */
-function organism_id_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
+function tripal_chado_organism_select_formatter_form($field, $instance,
+    $view_mode, $form, &$form_state) {
+
   $display = $instance['display'][$view_mode];
   $settings = $display['settings'];
   $element = array();
+  $term = NULL;
+  $bundle = NULL;
+
+  // Check to see if the organism bundle exists
+  $term = tripal_load_term_entity(array(
+    'namespace' => $field['settings']['semantic_web']['ns'],
+    'accession' => $field['settings']['semantic_web']['type']
+  ));
+  if ($term) {
+    $bundle = tripal_load_bundle_entity(array('term_id' => $term->id));
+  }
 
-  if ($display['type'] == 'text_trimmed' || $display['type'] == 'text_summary_or_trimmed') {
-    $element['trim_length'] = array(
-      '#title' => t('Length'),
-      '#type' => 'textfield',
-      '#size' => 20,
-      '#default_value' => $settings['trim_length'],
-      '#element_validate' => array('element_validate_integer_positive'),
-      '#required' => TRUE,
+  $element['instructions'] = array(
+    '#type' => 'item',
+    '#markup' => 'Please provide the format for viewing the organism. You
+      can specify the format using tokens that correspond to each field'
+  );
+
+  $element['field_display'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Display Format',
+    '#description' => t('Provide a mixture of text and/or tokens for the format.
+        For example: [organism__genus] [organism__species].  When displayed
+        the tokens will be replaced with the actual value.'),
+    '#default_value' => '[organism__genus] [organism__species]',
+  );
+
+  $element['field_display_entity'] = array(
+    '#type' => 'checkbox',
+    '#title' => 'Display teaser if available',
+    '#description' => t('If the organism that this field is associated with is
+        a published page then display the teaser rather use the display
+        format above.'),
+  );
+
+  $element['tokens'] = array(
+    '#type' => 'fieldset',
+    '#collapsed' => TRUE,
+    '#collapsible' => TRUE,
+    '#title' => 'Available Tokens'
+  );
+  $headers = array('Token', 'Description');
+  $rows = array();
+  $tokens = tripal_get_tokens($bundle);
+  foreach ($tokens as $token) {
+    $rows[] = array(
+      $token['token'],
+      $token['description'],
     );
   }
 
+
+  $table_vars = array(
+    'header'     => $headers,
+    'rows'       => $rows,
+    'attributes' => array(),
+    'sticky'     => FALSE,
+    'caption'    => '',
+    'colgroups'  => array(),
+    'empty'      => 'There are no tokens',
+  );
+  $project_details = theme('table', $table_vars);
+
+  $element['tokens']['list'] = array(
+    '#type' => 'item',
+    '#markup' => theme_table($table_vars),
+  );
+
   return $element;
 
 }

+ 1264 - 0
tripal_chado/includes/tripal_chado.fields.inc

@@ -0,0 +1,1264 @@
+<?php
+
+/**
+ * Implements hook_field_info().
+ */
+function tripal_chado_field_info() {
+  $fields = array(
+    'organism_id' => array(
+      'label' => t('Organism'),
+      'description' => t('A field for specifying an organism.'),
+      'default_widget' => 'tripal_chado_organism_select_widget',
+      'default_formatter' => 'tripal_chado_organism_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+    'dbxref_id' => array(
+      'label' => t('Cross reference'),
+      'description' => t('This record can be cross referenced with a record in
+          another online database. This field is intended for the most prominent
+          reference.  At a minimum, the database and accession must be provided.'),
+      'default_widget' => 'tripal_chado_dbxref_id_widget',
+      'default_formatter' => 'tripal_chado_dbxref_id_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+    'residues' => array(
+      'label' => t('Residues'),
+      'description' => t('A field for managing nucleotide and protein residues.'),
+      'default_widget' => 'tripal_chado_residue_textarea_widget',
+      'default_formatter' => 'tripal_chado_residues_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+    'md5checksum' => array(
+      'label' => t('MD5 checksum'),
+      'description' => t('A field for generating MD5 checksum for a sequence.'),
+      'default_widget' => 'tripal_chado_md5checksum_checkbox_widget',
+      'default_formatter' => 'tripal_chado_md5checksum_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+    'seqlen' => array(
+      'label' => t('Sequence length'),
+      'description' => t('A field for calculating the length of a sequence.'),
+      'default_widget' => 'tripal_chado_seqlen_hidden_widget',
+      'default_formatter' => 'tripal_chado_seqlen_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+    // The field provides a widget for adding new properties
+    // to an entity that is connected to a base table that has a prop table
+    // in Chado.
+    'kvproperty_adder' => array(
+      'label' => t('Add a Property Type'),
+      'description' => t('This record may have any number of properties. Use
+          this field to first add the type.'),
+      'default_widget' => 'tripal_chado_kvproperty_adder_widget',
+      //'default_formatter' => 'tripal_chado_kvproperty_adder_formatter',
+      'default_formatter' => 'hidden',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+    // The field provides form elements for adding a property to an entity
+    // that in turn gets stored in a prop table of Chado (e.g. featureprop,
+    // stockprop, etc).
+    'kvproperty' => array(
+      'label' => t('Add a Property'),
+      'description' => t('Add details about this property.'),
+      'default_widget' => 'tripal_chado_kvproperty_widget',
+      'default_formatter' => 'tripal_chado_kvproperty_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+
+    // The field provides form elements for adding multiple dbxrefs to an
+    // entity that in turn get stored in a [base]_dbxref table of Chado
+    // (e.g. organism_dbxref, feature_dbxref).  This is different
+    // from the dbxref_id field as that is specific to a dbxref_id in
+    // a base table.
+    'dbxref' => array(
+      'label' => t('Cross references'),
+      'description' => t('This record can be cross referenced with a record in
+          another online database. This field is intended for one or more
+          references.  At a minimum, the database and accession must be provided.'),
+      'default_widget' => 'tripal_chado_dbxref_widget',
+      'default_formatter' => 'tripal_chado_dbxref_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+    // The field provides a widget for adding new vocabularies for cvterm
+    // linker tables. This will allow cvterms to be grouped by vocabulary
+    // ('category').
+    'cvterm_class_adder' => array(
+      'label' => t('Add an Annotation Type'),
+      'description' => t('This record may have any number of types of
+          annotations. Use this field to first add the type.'),
+      'default_widget' => 'tripal_chado_cvterm_class_adder_widget',
+      //'default_formatter' => 'tripal_chado_cvterm_class_adder_formatter',
+      'default_formatter' => 'hidden',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+    // The field provides form elements for adding multiple cvterms to an
+    // entity that in turn get stored in a [base]_cvterm table of Chado
+    // (e.g. feature_cvterm).
+    'cvterm' => array(
+      'label' => t('Annotations'),
+      'description' => t('This record can be annotated with terms
+          from other vocabularies.'),
+      'default_widget' => 'tripal_chado_cvterm_widget',
+      'default_formatter' => 'tripal_chado_cvterm_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+
+    'synonym' => array(
+      'label' => t('Synonyms'),
+      'description' => t('Adds an alternative name (synonym or alias) to this record.'),
+      'default_widget' => 'tripal_chado_synonym_widget',
+      'default_formatter' => 'tripal_chado_synonym_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+
+    'pub' => array(
+      'label' => t('Publications'),
+      'description' => t('Associates a publication (e.g. journal article, conference proceedings, book chapter, etc.) with this record.'),
+      'default_widget' => 'tripal_chado_pub_widget',
+      'default_formatter' => 'tripal_chado_pub_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    ),
+  );
+  return $fields;
+}
+
+/**
+ * Implements hook_field_formatter_settings_summary.
+ */
+function tripal_chado_field_formatter_settings_summary($field, $instance, $view_mode) {
+
+  $summary = '';
+  switch ($field['type']) {
+    case 'organism_id':
+      $summary = 'Organisms can be displayed in vaious ways.';
+      break;
+    default:
+      $summary = '';
+  }
+
+  return $summary;
+}
+
+/**
+ * Implements hook_field_formatter_settings_form.
+ */
+function tripal_chado_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
+  $element = array();
+  switch ($field['type']) {
+    case 'organism_id':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/organism_id');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/organism_id');
+      $element = tripal_chado_organism_select_formatter_form($field, $instance, $view_mode, $form, $form_state);
+      break;
+  }
+
+  return $element;
+}
+
+/**
+ * Implements hook_field_formatter_view().
+ */
+function tripal_chado_field_formatter_view($entity_type, $entity, $field,
+    $instance, $langcode, $items, $display) {
+
+  $element = array();
+  switch ($display['type']) {
+    case 'tripal_chado_organism_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/organism_id');
+      tripal_chado_organism_select_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_dbxref_id_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/dbxref_id');
+      tripal_chado_dbxref_id_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_dbxref_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/dbxref');
+      tripal_chado_dbxref_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_cvterm_class_adder_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/cvterm_class_adder');
+      tripal_chado_cvterm_class_adder_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_cvterm_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/cvterm');
+      tripal_chado_cvterm_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_md5checksum_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/md5checksum');
+      tripal_chado_md5checksum_checkbox_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_residues_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/residues');
+      tripal_chado_residues_textarea_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_seqlen_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/seqlen');
+      tripal_chado_seqlen_hidden_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_kvproperty_adder_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/kvproperty_adder');
+      tripal_chado_kvproperty_adder_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_kvproperty_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/kvproperty');
+      tripal_chado_kvproperty_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_synonym_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/synonym');
+      tripal_chado_synonym_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+    case 'tripal_chado_pub_formatter':
+      module_load_include('inc', 'tripal_chado', 'includes/fields/pub');
+      tripal_chado_pub_formatter($element, $entity_type, $entity, $field,
+          $instance, $langcode, $items, $display);
+      break;
+  }
+  return $element;
+}
+
+/**
+ * Implements hook_field_widget_form().
+ */
+function tripal_chado_field_widget_form(&$form, &$form_state, $field,
+    $instance, $langcode, $items, $delta, $element) {
+
+  $widget = $element;
+  switch ($instance['widget']['type']) {
+    case 'tripal_chado_organism_select_widget':
+      // Make sure the include files get parsed now and for the form submits.
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/organism_id');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/organism_id');
+      // Update the widget with the new field.
+      tripal_chado_organism_select_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_dbxref_id_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/dbxref_id');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/dbxref_id');
+      tripal_chado_dbxref_id_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_dbxref_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/dbxref');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/dbxref');
+      tripal_chado_dbxref_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_cvterm_class_adder_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/cvterm_class_adder');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/cvterm_class_adder');
+      tripal_chado_cvterm_class_adder_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_cvterm_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/cvterm');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/cvterm');
+      tripal_chado_cvterm_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_md5checksum_checkbox_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/md5checksum');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/md5checksum');
+      tripal_chado_md5checksum_checkbox_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_residues_textarea_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/residues');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/residues');
+      tripal_chado_residues_textarea_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_seqlen_hidden_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/seqlen');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/seqlen');
+      tripal_chado_seqlen_hidden_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_kvproperty_adder_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/kvproperty_adder');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/kvproperty_adder');
+      tripal_chado_kvproperty_adder_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_kvproperty_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/kvproperty');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/kvproperty');
+      tripal_chado_kvproperty_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_synonym_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/synonym');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/synonym');
+      tripal_chado_synonym_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+    case 'tripal_chado_pub_widget':
+      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/pub');
+      module_load_include('inc', 'tripal_chado', 'includes/fields/pub');
+      tripal_chado_pub_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
+      break;
+  }
+  return $widget;
+}
+/**
+ * Implements hook_field_widget_info().
+ */
+function tripal_chado_field_widget_info() {
+  return array(
+    'tripal_chado_organism_select_widget' => array(
+      'label' => t('Organism Select'),
+      'field types' => array('organism_id')
+    ),
+    'tripal_chado_dbxref_id_widget' => array(
+      'label' => t('Cross reference'),
+      'field types' => array('dbxref_id'),
+      'description' => t('This record can be cross referenced with a record in
+        another online database. This field is intended for the most
+        prominent reference.  At a minimum, the database and accession
+        must be provided.'),
+    ),
+    'tripal_chado_dbxref_widget' => array(
+      'label' => t('Cross references'),
+      'field types' => array('dbxref'),
+      'description' => t('This record can be cross referenced with a record
+        in another online database. This field is intended for the most
+        prominent reference.  At a minimum, the database and accession
+        must be provided.'),
+    ),
+    'tripal_chado_cvterm_class_adder_widget' => array(
+      'label' => t('Add an Annotation'),
+      'field types' => array('cvterm_class_adder'),
+    ),
+    'tripal_chado_cvterm_widget' => array(
+      'label' => t('Annotations'),
+      'field types' => array('cvterm'),
+      'description' => t('This record can be annotated with terms
+          from other vocabularies.'),
+    ),
+    'tripal_chado_md5checksum_checkbox_widget' => array(
+      'label' => t('MD5 Checksum Checkbox'),
+      'field types' => array('md5checksum'),
+    ),
+    'tripal_chado_residues_textarea_widget' => array(
+      'label' => t('Residues'),
+      'field types' => array('residues'),
+    ),
+    'tripal_chado_seqlen_hidden_widget' => array(
+      'label' => t('Sequence Length'),
+      'field types' => array('seqlen'),
+    ),
+    'tripal_chado_kvproperty_adder_widget' => array(
+      'label' => t('Add a Property'),
+      'field types' => array('kvproperty_adder'),
+    ),
+    'tripal_chado_kvproperty_widget' => array(
+      'label' => t('Property'),
+      'field types' => array('kvproperty'),
+    ),
+    'tripal_chado_synonym_widget' => array(
+      'label' => t('Synonyms'),
+      'field types' => array('synonym'),
+    ),
+    'tripal_chado_pub_widget' => array(
+      'label' => t('Publications'),
+      'field types' => array('pub'),
+    ),
+  );
+}
+/**
+ * Returns the values of the field from the $form_state.
+ */
+function tripal_chado_get_field_form_values($field_name, $form_state, $delta = 0, $child = NULL) {
+  $value = NULL;
+  // The form_state must have the 'values' key. If not then just return.
+  if (!array_key_exists('values', $form_state)) {
+    return $value;
+  }
+
+  // If the field name is not in the form_state['values'] then return.
+  if (!array_key_exists($field_name, $form_state['values'])) {
+    return $value;
+  }
+
+  // Iterate through the values looking for the field_name provided.
+  foreach ($form_state['values'][$field_name] as $langcode => $items) {
+    if (!array_key_exists($delta, $items)) {
+      continue;
+    }
+    $item = $items[$delta];
+    if ($child){
+      if(array_key_exists($child, $item) and $item[$child] != '') {
+        $value = $item[$child];
+      }
+    }
+    else {
+      $value = $item['value'];
+    }
+  }
+  return $value;
+}
+
+/**
+ * Sets the values of the field from the $form_state.
+ */
+function tripal_chado_set_field_form_values($field_name, &$form_state, $newvalue, $delta = 0, $child = NULL) {
+  // The form_state must have the 'values' key. If not then just return.
+  if (!array_key_exists('values', $form_state)) {
+    return FALSE;
+  }
+
+  // If the field name is not in the form_state['values'] then reutrn.
+  if (!array_key_exists($field_name, $form_state['values'])) {
+    return FALSE;
+  }
+
+  foreach ($form_state['values'][$field_name] as $langcode => $items) {
+    if ($child) {
+      $form_state['values'][$field_name][$langcode][$delta][$child] = $newvalue;
+    }
+    else {
+      $form_state['values'][$field_name][$langcode][$delta]['value'] = $newvalue;
+    }
+  }
+  return TRUE;
+}
+
+/**
+ * Implements hook_field_widget_form_alter().
+ */
+function tripal_chado_field_widget_form_alter(&$element, &$form_state, $context) {
+
+  if (array_key_exists('#field_name', $element)) {
+    $field_name = $element['#field_name'];
+    $matches = array();
+
+    if (preg_match('/(.+?)__(.+?)$/', $field_name, $matches)) {
+      $tablename = $matches[1];
+      $colname = $matches[2];
+      $schema = chado_get_schema($tablename);
+
+      // The timelastmodified field exists in many Chado tables.  We want
+      // the form element to update to the most recent time rather than the time
+      // in the database.
+      if ($colname == 'timelastmodified' and $schema['fields'][$colname]['type'] == 'datetime') {
+        // We want the default value for the field to be the current time.
+        $element['#default_value']['value'] = format_date(time(), 'custom', "Y-m-d H:i:s", 'UTC');
+        $element['#date_items']['value'] = $element['#default_value']['value'];
+      }
+      // We want the date combo fieldset to be collaspible so we will
+      // add our own theme_wrapper to replace the one added by the date
+      // module.
+      if (array_key_exists($colname, $schema['fields']) and $schema['fields'][$colname]['type'] == 'datetime') {
+        $element['#theme_wrappers'] = array('tripal_chado_date_combo');
+      }
+    }
+  }
+}
+
+/**
+ * Implements hook_field_formatter_info().
+ */
+function tripal_chado_field_formatter_info() {
+  return array(
+    'tripal_chado_organism_formatter' => array(
+      'label' => t('Organism'),
+      'field types' => array('organism_id')
+    ),
+    'tripal_chado_dbxref_id_formatter' => array(
+      'label' => t('Cross reference'),
+      'field types' => array('dbxref_id')
+    ),
+    'tripal_chado_dbxref_formatter' => array(
+      'label' => t('Cross references'),
+      'field types' => array('dbxref')
+    ),
+    'tripal_chado_cvterm_class_adder_formatter' => array(
+      'label' => t('Add an Annotation'),
+      'field types' => array('cvterm_class_adder')
+    ),
+    'tripal_chado_cvterm_formatter' => array(
+      'label' => t('Annotations'),
+      'field types' => array('cvterm')
+    ),
+    'tripal_chado_md5checksum_formatter' => array(
+      'label' => t('MD5 checksum'),
+      'field types' => array('md5checksum')
+    ),
+    'tripal_chado_residues_formatter' => array(
+      'label' => t('Residues'),
+      'field types' => array('residues')
+    ),
+    'tripal_chado_seqlen_formatter' => array(
+      'label' => t('Sequence length'),
+      'field types' => array('seqlen')
+    ),
+    'tripal_chado_kvproperty_adder_formatter' => array(
+      'label' => t('Add a Property'),
+      'field types' => array('kvproperty_adder')
+    ),
+    'tripal_chado_kvproperty_formatter' => array(
+      'label' => t('Property'),
+      'field types' => array('kvproperty')
+    ),
+    'tripal_chado_synonym_formatter' => array(
+      'label' => t('Synonyms'),
+      'field types' => array('synonym')
+    ),
+    'tripal_chado_pub_formatter' => array(
+      'label' => t('Publications'),
+      'field types' => array('pub')
+    ),
+  );
+}
+
+/**
+ * Returns a $field_info array for a field based on a database column.
+ *
+ */
+function tripal_chado_add_bundle_fields_base_fields_defaults($table_name, $schema, $column_name) {
+  $details = $schema['fields'][$column_name];
+
+  // Create an array with information about this field.
+  $field = array(
+    'field_type' => '',
+    'widget_type' => '',
+    'description' => '',
+    'label' => ucwords(preg_replace('/_/', ' ', $column_name)),
+    'is_required' => 0,
+    'storage' => 'field_chado_storage',
+    'widget_settings' => array(
+      'display_label' => 1
+    ),
+    'field_settings' => array(
+      // The table in Chado where this field maps to.
+      'chado_table' => $table_name,
+      // The column in the Chado table that this field maps to.
+      'chado_column' => $column_name,
+      'semantic_web' => array(
+        // The type is the term from a vocabulary that desribes this field..
+        'type' => '',
+        // The namepsace for the vocabulary (e.g. 'foaf').
+        'ns' => '',
+        // The URL for the namespace.  It must be that the type can be
+        // appended to the URL.
+        'nsurl' => '',
+      ),
+    ),
+  );
+
+  // Alter the field info array depending on the column details.
+  switch($details['type']) {
+    case 'char':
+      $field['field_type'] = 'text';
+      $field['widget_type'] = 'text_textfield';
+      $field['field_settings']['max_length'] = $details['length'];
+      break;
+    case 'varchar':
+      $field['field_type'] = 'text';
+      $field['widget_type'] = 'text_textfield';
+      $field['field_settings']['max_length'] = $details['length'];
+      break;
+    case 'text':
+      $field['field_type'] = 'text';
+      $field['widget_type'] = 'text_textarea';
+      $field['field_settings']['max_length'] = 17179869184;
+      $field['field_settings']['text_processing'] = 1;
+      $field['format'] = filter_default_format();
+      break;
+    case 'blob':
+      // not sure how to support a blob field.
+      continue;
+      break;
+    case 'int':
+      $field['field_type'] = 'number_integer';
+      $field['widget_type'] = 'number';
+      break;
+    case 'float':
+      $field['field_type'] = 'number_float';
+      $field['widget_type'] = 'number';
+      $field['field_settings']['precision'] = 10;
+      $field['field_settings']['scale'] = 2;
+      $field['field_settings']['decimal_separator'] = '.';
+      break;
+    case 'numeric':
+      $field['field_type'] = 'number_decimal';
+      $field['widget_type'] = 'number';
+      break;
+    case 'serial':
+      // Serial fields are most likely not needed as a field.
+      break;
+    case 'boolean':
+      $field['field_type'] = 'list_boolean';
+      $field['widget_type'] = 'options_onoff';
+      $field['field_settings']['allowed_values'] = array(0 => "No", 1 => "Yes");
+      break;
+    case 'datetime':
+      // Use the Drupal Date and Date API to create the field/widget
+      $field['field_type'] = 'datetime';
+      $field['widget_type'] = 'date_select';
+      $field['widget_settings']['increment'] = 1;
+      $field['widget_settings']['tz_handling'] = 'none';
+      $field['widget_settings']['collapsible'] = TRUE;
+
+      // TODO: Add settings so that the minutes increment by 1.
+      // And turn off the timezone, as the Chado field doesn't support it.
+      break;
+  }
+
+  // Set some default semantic web information
+  if ($column_name == 'name') {
+    $field['field_settings']['semantic_web']['type'] = 'name';
+    $field['field_settings']['semantic_web']['ns'] = 'foaf';
+    $field['field_settings']['semantic_web']['nsurl'] = 'http://xmlns.com/foaf/0.1/';
+  }
+  if ($column_name == 'description' or $column_name == 'definition' or
+      $column_name == 'comment') {
+    $field['field_settings']['semantic_web']['type'] = 'description';
+    $field['field_settings']['semantic_web']['ns'] = 'hydra';
+    $field['field_settings']['semantic_web']['nsurl'] = 'http://www.w3.org/ns/hydra/core#';
+  }
+
+  //
+  // GENERIC COLUMNS
+  //
+  if ($field['field_settings']['chado_column'] =='organism_id') {
+    $field['field_type'] = 'organism_id';
+    $field['widget_type'] = 'tripal_chado_organism_select_widget';
+    $field['label'] = 'Organism';
+    $field['description'] = 'Select an organism.';
+    $field['field_settings']['semantic_web']['type'] = 'organism';
+    $field['field_settings']['semantic_web']['ns'] = 'local';
+    $field['field_settings']['semantic_web']['nsurl'] = '';
+
+  }
+  elseif ($field['field_settings']['chado_column'] =='dbxref_id') {
+    $field['field_type'] = 'dbxref_id';
+    $field['widget_type'] = 'tripal_chado_primary_dbxref_widget';
+    $field['label'] = 'Cross Reference';
+    $field['description'] = 'This record can be cross referenced with a ' .
+        'record in another online database. The primary reference is for the ' .
+        'most prominent reference.  At a minimum, the database and accession ' .
+        'must be provided.  To remove a set reference, change the database ' .
+        'field to "Select a Database".';
+  }
+  elseif ($field['label'] == 'Timeaccessioned') {
+    $field['label'] = 'Time Accessioned';
+    $field['description'] = 'Please enter the time that this record was first added to the database.';
+  }
+  elseif ($field['label'] == 'Timelastmodified') {
+    $field['label'] = 'Time Last Modified';
+    $field['description'] = 'Please enter the time that this record was last modified. The default is the current time.';
+  }
+  //
+  // ORGANISM TABLE
+  //
+  elseif ($field['field_settings']['chado_table'] == 'organism' and $field['field_settings']['chado_column'] == 'comment') {
+    $field['label'] = 'Description';
+  }
+  //
+  // FEATURE TABLE
+  //
+  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'uniquename') {
+    $field['field_type'] = 'text';
+    $field['widget_type'] = 'text_textfield';
+    $field['field_settings']['text_processing'] = 0;
+    $field['field_settings']['semantic_web']['type'] = 'name';
+    $field['field_settings']['semantic_web']['ns'] = 'foaf';
+    $field['field_settings']['semantic_web']['nsurl'] = 'http://xmlns.com/foaf/0.1/';
+  }
+  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'md5checksum') {
+    $field['field_type'] = 'md5checksum';
+    $field['widget_type'] = 'tripal_chado_md5checksum_checkbox_widget';
+    $field['label'] = 'MD5 Checksum';
+    $field['description'] = 'Generate an MD5 checksum for the sequence.';
+  }
+  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'seqlen') {
+    $field['field_type'] = 'seqlen';
+    $field['widget_type'] = 'tripal_chado_seqlen_hidden_widget';
+    $field['label'] = 'Seqlen';
+    $field['description'] = 'The length of the residues.';
+  }
+  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'residues') {
+    $field['field_type'] = 'residues';
+    $field['widget_type'] = 'tripal_chado_residues_textarea_widget';
+    $field['label'] = 'Residues';
+    $field['description'] = 'Please provide an IUPAC compatible residues for this feature. Spaces and new lines are allowed.';
+  }
+  //
+  // ANALYSIS TABLE
+  //
+  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'program') {
+    $field['field_settings']['semantic_web']['type'] = 'SoftwareApplication';
+    $field['field_settings']['semantic_web']['ns'] = 'schema';
+    $field['field_settings']['semantic_web']['nsurl'] = 'https://schema.org/';
+    $field['description'] = 'The program name (e.g. blastx, blastp, sim4, genscan. If the analysis was not derived from a software package then provide a very brief description of the pipeline, workflow or method.';
+    $field['label'] = 'Program, Pipeline, Workflow or Method Name.';
+  }
+  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourceuri') {
+    $field['field_type'] = 'text';
+    $field['widget_type'] = 'text_textfield';
+    $field['field_settings']['text_processing'] = 0;
+    $field['label'] = 'Source URL';
+    $field['description'] = 'The URL where the original source data was derived.  Ideally, this should link to the page where more information about the source data can be found.';
+  }
+  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourcename') {
+    $field['label'] = 'Source Name';
+    $field['description'] = 'The name of the source data. This could be a file name, data set or a small description for how the data was collected. For long descriptions use the larger description field.';
+  }
+  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourceversion') {
+    $field['label'] = 'Source Version';
+    $field['description'] = 'If hte source data set has a version include it here.';
+  }
+  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'algorithm') {
+    $field['label'] = 'Source Version';
+    $field['description'] = 'The name of the algorithm used to produce the dataset if different from the program.';
+  }
+  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'programversion') {
+    $field['label'] = 'Program Version';
+    $field['description'] = 'The version of the program used to perform this analysis. (e.g. TBLASTX 2.0MP-WashU [09-Nov-2000]. Enter "n/a" if no version is available or applicable.';
+  }
+  //
+  // PROJECT TABLE
+  //
+  elseif ($field['field_settings']['chado_table'] == 'project' and $field['field_settings']['chado_column'] == 'description') {
+    $field['label'] = 'Short Description';
+  }
+  return $field;
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * The field_ui_display_overview_form is used for formatting the display
+ * or layout of fields attached to an entity and shown on the entity view page.
+ *
+ * This function removes the cvterm class and property adder field as those are
+ * really not meant for users to show or manage.
+ */
+function tripal_chado_form_field_ui_display_overview_form_alter(&$form, &$form_state, $form_id) {
+  // Remove the kvproperty_addr field as it isn't ever displayed. It's just used
+  // on the add/edit form of an entity for adding new property fields.
+  $fields_names = element_children($form['fields']);
+  foreach ($fields_names as $field_name) {
+    $field_info = field_info_field($field_name);
+    if ($field_info['type'] == 'kvproperty_adder') {
+      unset($form['fields'][$field_name]);
+    }
+    if ($field_info['type'] == 'cvterm_class_adder') {
+      unset($form['fields'][$field_name]);
+    }
+  }
+}
+/**
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * The field_ui_field_overview_form is used for ordering and configuring the
+ * fields attached to an entity.
+ *
+ * This function removes the property adder field as that is really not meant
+ * for users to show or manage.
+ */
+function tripal_chado_form_field_ui_field_overview_form_alter(&$form, &$form_state, $form_id) {
+  // Remove the kvproperty_addr field as it isn't ever displayed. It's just used
+  // on the add/edit form of an entity for adding new property fields.
+  $fields_names = element_children($form['fields']);
+  foreach ($fields_names as $field_name) {
+    $field_info = field_info_field($field_name);
+    if ($field_info['type'] == 'kvproperty_adder') {
+      unset($form['fields'][$field_name]);
+    }
+    if ($field_info['type'] == 'cvterm_class_adder') {
+      unset($form['fields'][$field_name]);
+    }
+  }
+}
+
+/**
+ * Implements hook_field_is_empty().
+ */
+function tripal_chado_field_is_empty($item, $field) {
+
+  // If there is no value field then the field is empty.
+  if (!array_key_exists('value', $item)) {
+    return TRUE;
+  }
+
+  // Iterate through all of the fields and if at least one has a value
+  // the field is not empty.
+  foreach ($item as $form_field_name => $value) {
+    if (isset($value) and $value != NULL and $value != '') {
+      return FALSE;
+    }
+  }
+
+  // Otherwise, the field is empty.
+  return TRUE;
+}
+
+
+
+/**
+ * Implements hook_add_bundle_fields().
+ */
+function tripal_chado_add_bundle_fields($entity_type, $bundle, $term) {
+
+  $bundle_name = $bundle->name;
+
+  // This array will hold details that map the bundle to tables in Chado.
+  $bundle_data = array();
+
+  // Get the cvterm that corresponds to this TripalTerm object.
+  $vocab = entity_load('TripalVocab', array($term->vocab_id));
+  $vocab = reset($vocab);
+  $match = array(
+    'dbxref_id' => array(
+      'db_id' => array(
+        'name' => $vocab->namespace,
+      ),
+      'accession' => $term->accession
+    ),
+  );
+  $cvterm = chado_generate_var('cvterm', $match);
+
+  // The organism table does not have a type_id so we won't ever find
+  // a record for it in the tripal_cv_defaults table.
+  if ($cvterm->name == 'organism') {
+    $bundle_data = array(
+      'cv_id' => $cvterm->cv_id->cv_id,
+      'cvterm_id' => $cvterm->cvterm_id,
+      'data_table' => 'organism',
+      'type_table' => 'organism',
+      'field' =>  '',
+    );
+  }
+  // The analysis table does not have a type_id so we won't ever find
+  // a record for it in the tripalcv_defaults table.
+  else if ($cvterm->name == 'analysis') {
+    $bundle_data = array(
+      'cv_id' => $cvterm->cv_id->cv_id,
+      'cvterm_id' => $cvterm->cvterm_id,
+      'data_table' => 'analysis',
+      'type_table' => 'analysis',
+      'field' =>  '',
+    );
+  }
+  else if ($cvterm->name == 'project') {
+    $bundle_data = array(
+      'cv_id' => $cvterm->cv_id->cv_id,
+      'cvterm_id' => $cvterm->cvterm_id,
+      'data_table' => 'project',
+      'type_table' => 'project',
+      'field' =>  '',
+    );
+  }
+  else {
+    // TODO: WHAT TO DO IF A VOCABULARY IS USED AS A DEFAULT FOR MULTIPLE
+    // TABLES.
+    // Look to see if this vocabulary is used as a default for any table.
+    $default = db_select('tripal_cv_defaults', 't')
+      ->fields('t')
+      ->condition('cv_id', $cvterm->cv_id->cv_id)
+      ->execute()
+      ->fetchObject();
+    if ($default) {
+      $bundle_data = array(
+        'cv_id' => $cvterm->cv_id->cv_id,
+        'cvterm_id' => $cvterm->cvterm_id,
+        'data_table' => $default->table_name,
+        'type_table' => $default->table_name,
+        'field' =>  $default->field_name,
+      );
+    }
+  }
+
+  // Save the mapping information so that we can reuse it when we need to
+  // look things up for later for an entity
+  tripal_set_bundle_variable('chado_cvterm_id', $bundle->id, $bundle_data['cvterm_id']);
+  tripal_set_bundle_variable('chado_table', $bundle->id, $bundle_data['data_table']);
+  tripal_set_bundle_variable('chado_column', $bundle->id, $bundle_data['field']);
+
+  //////////////////////////////////////////////////////////////////////////////
+  // ADD FIELDS TO BUNDLE
+  ////////////////////////////////////////////////////////////////////////////
+
+  ////
+  //
+  // Base table fields.
+  //
+  // Adds the fields for the base table to the entity.  Adds fields
+  // for all columns including FK fields.  Excludes primary key and the
+  // type_id field (that's inherent in the bundle).
+  tripal_chado_add_bundle_fields_base_fields($entity_type, $bundle_name, $bundle_data);
+
+  ////
+  //
+  // Property table fields.
+  //
+  // Check to see if there are any property tables with FKs to this
+  // base table. If so, add the fields for that type of table.
+  $prop_table = $bundle_data['data_table'] . 'prop';
+  if (chado_table_exists($prop_table)) {
+    tripal_chado_add_bundle_fields_kvproperty_adder_field($entity_type, $bundle_name, $prop_table, $bundle_data['data_table']);
+  }
+
+  ////
+  //
+  // Dbxref table fields.
+  //
+  // Check to see if there are any dbxref tables with FKs to this
+  // base table. If so, add the fields for that type of table.
+  $dbxref_table = $bundle_data['data_table'] . '_dbxref';
+  if (chado_table_exists($dbxref_table)) {
+    tripal_chado_add_bundle_fields_dbxref_field($entity_type, $bundle_name, $dbxref_table, $bundle_data['data_table']);
+  }
+
+  ////
+  //
+  // Cvterm table fields.
+  //
+  // Check to see if there are any cvterm tables with FKs to this
+  // base table. If so, add the fields for that type of table.
+  $cvterm_table = $bundle_data['data_table'] . '_cvterm';
+  if (chado_table_exists($cvterm_table)) {
+    tripal_chado_add_bundle_fields_cvterm_class_adder_field($entity_type, $bundle_name, $cvterm_table, $bundle_data['data_table']);
+  }
+
+
+  ////
+  //
+  // Synonym table fields.
+  //
+  // Check to see if there are any synonym tables with FKs to this
+  // base table. If so, add the fields for that type of table.
+  $syn_table = $bundle_data['data_table'] . '_synonym';
+  if (chado_table_exists($syn_table)) {
+    tripal_chado_add_bundle_fields_synonym_field($entity_type, $bundle_name, $syn_table, $bundle_data['data_table']);
+  }
+
+  ////
+  //
+  // Pub table fields.
+  //
+  // Check to see if there are any pub tables with FKs to this
+  // base table. If so, add the fields for that type of table.
+  $pub_table = $bundle_data['data_table'] . '_pub';
+  if (chado_table_exists($pub_table)) {
+    tripal_chado_add_bundle_fields_pub_field($entity_type, $bundle_name, $pub_table, $bundle_data['data_table']);
+  }
+}
+
+/**
+ * Adds the fields for managing xrefs that are stored in a [base]_dbxref table.
+ *
+ * @param $entity_type
+ * @param $bundle_name
+ * @param $base_table
+ * @param $dbxref_table
+ */
+function tripal_chado_add_bundle_fields_dbxref_field($entity_type_name, $bundle_name, $dbxref_table, $base_table) {
+  // We already have a dbxref_id field.
+  $field_name = $dbxref_table;
+  $schema = chado_get_schema($dbxref_table);
+  $pkey = $schema['primary key'][0];
+
+  // Initialize the field array.
+  $field_info = array(
+    'field_type' => 'dbxref',
+    'widget_type' => 'tripal_fields_dbxfref_widget',
+    'widget_settings' => array('display_label' => 1),
+    'description' => '',
+    'label' => 'Cross References',
+    'is_required' => 0,
+    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+    'storage' => 'field_chado_storage',
+    'field_settings' => array(
+      // The Chado table that this field maps to.
+      'chado_table' => $dbxref_table,
+      // The column in the chado table that this field maps to.
+      'chado_column' => $pkey,
+      // The base table that this field is connected to.
+      'base_table' => $base_table,
+      'semantic_web' => array(
+        // The type is the term from a vocabulary that desribes this field..
+        'type' => '',
+        // The namepsace for the vocabulary (e.g. 'foaf').
+        'ns' => '',
+        // The URL for the namespace.  It must be that the type can be
+        // appended to the URL.
+        'nsurl' => '',
+      ),
+    ),
+  );
+
+  // If the base table has a 'dbxref_id' then change the label to
+  // indicate these are secondary cross references.
+  $schema = chado_get_schema($base_table);
+  if (array_key_exists('dbxref_id', $schema['fields'])) {
+    $field_info['label'] = 'Secondary Cross References';
+  }
+  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+}
+/**
+ * Adds the fields for managing xrefs that are stored in a [base]_dbxref table.
+ *
+ * @param $entity_type
+ * @param $bundle_name
+ * @param $base_table
+ * @param $dbxref_table
+ */
+function tripal_chado_add_bundle_fields_synonym_field($entity_type_name, $bundle_name, $syn_table, $base_table) {
+  // We already have a dbxref_id field.
+  $field_name = $syn_table;
+  $schema = chado_get_schema($syn_table);
+  $pkey = $schema['primary key'][0];
+
+  // Initialize the field array.
+  $field_info = array(
+    'field_type' => 'synonym',
+    'widget_type' => 'tripal_fields_synonym_widget',
+    'widget_settings' => array('display_label' => 1),
+    'description' => '',
+    'label' => 'Synonyms',
+    'is_required' => 0,
+    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+    'storage' => 'field_chado_storage',
+    'field_settings' => array(
+      // The Chado table that this field maps to.
+      'chado_table' => $syn_table,
+      // The column in the chado table that this field maps to.
+      'chado_column' => $pkey,
+      // The base table that this field is connected to.
+      'base_table' => $base_table,
+      'semantic_web' => array(
+        // The type is the term from a vocabulary that desribes this field..
+        'type' => '',
+        // The namepsace for the vocabulary (e.g. 'foaf').
+        'ns' => '',
+        // The URL for the namespace.  It must be that the type can be
+        // appended to the URL.
+        'nsurl' => '',
+      ),
+    ),
+  );
+
+  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+}
+/**
+ * Adds the fields for managing xrefs that are stored in a [base]_dbxref table.
+ *
+ * @param $entity_type
+ * @param $bundle_name
+ * @param $base_table
+ * @param $dbxref_table
+ */
+function tripal_chado_add_bundle_fields_pub_field($entity_type_name, $bundle_name, $pub_table, $base_table) {
+  // We already have a dbxref_id field.
+  $field_name = $pub_table;
+  $schema = chado_get_schema($pub_table);
+  $pkey = $schema['primary key'][0];
+
+  // Initialize the field array.
+  $field_info = array(
+    'field_type' => 'pub',
+    'widget_type' => 'tripal_fields_pub_widget',
+    'widget_settings' => array('display_label' => 1),
+    'description' => '',
+    'label' => 'Publications',
+    'is_required' => 0,
+    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+    'storage' => 'field_chado_storage',
+    'field_settings' => array(
+      // The Chado table that this field maps to.
+      'chado_table' => $pub_table,
+      // The column in the chado table that this field maps to.
+      'chado_column' => $pkey,
+      // The base table that this field is connected to.
+      'base_table' => $base_table,
+      'semantic_web' => array(
+        // The type is the term from a vocabulary that desribes this field..
+        'type' => '',
+        // The namepsace for the vocabulary (e.g. 'foaf').
+        'ns' => '',
+        // The URL for the namespace.  It must be that the type can be
+        // appended to the URL.
+        'nsurl' => '',
+      ),
+    ),
+  );
+
+  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+}
+/**
+ * Adds the fields for managing properties that are stored in a prop table.
+ *
+ * @param $entity_type_name
+ * @param $bundle_name
+ * @param $kv_table
+ */
+function tripal_chado_add_bundle_fields_kvproperty_adder_field($entity_type_name, $bundle_name, $kv_table, $base_table) {
+  $field_name = $kv_table;
+
+  // Initialize the field array.
+  $field_info = array(
+    'field_type' => 'kvproperty_adder',
+    'widget_type' => 'tripal_fields_kvproperty_adder_widget',
+    'field_settings' => array(
+      'base_table' => $base_table,
+    ),
+    'storage' => 'field_chado_storage',
+    'widget_settings' => array('display_label' => 1),
+    'description' => '',
+    'label' => 'Additional Properties',
+    'is_required' => 0,
+  );
+  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+}
+/**
+ * Adds the fields for managing properties that are stored in a prop table.
+ *
+ * @param $entity_type_name
+ * @param $bundle_name
+ * @param $kv_table
+ */
+function tripal_chado_add_bundle_fields_cvterm_class_adder_field($entity_type_name, $bundle_name, $cvterm_table, $base_table) {
+  // First add a generic property field so that users can add new property types.
+  $field_name = $cvterm_table;
+
+  // Initialize the field array.
+  $field_info = array(
+    'field_type' => 'cvterm_class_adder',
+    'widget_type' => 'tripal_fields_cvterm_class_adder_widget',
+    'field_settings' => array(
+      'base_table' => $base_table,
+    ),
+    'storage' => 'field_chado_storage',
+    'widget_settings' => array('display_label' => 1),
+    'description' => '',
+    'label' => 'Additional Annotation Types',
+    'is_required' => 0,
+  );
+  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+}
+/**
+ * Adds the fields for the base table to the entity.
+ */
+function tripal_chado_add_bundle_fields_base_fields($entity_type_name, $bundle_name, $bundle_data) {
+
+  $table_name = $bundle_data['data_table'];
+  $type_table = $bundle_data['type_table'];
+  $type_field = $bundle_data['field'];
+
+  // Iterate through the columns of the table and see if fields have been
+  // created for each one. If not, then create them.
+  $schema = chado_get_schema($table_name);
+  $columns = $schema['fields'];
+  foreach ($columns as $column_name => $details) {
+    $field_name = $table_name . '__' . $column_name;
+
+    // Skip the primary key field.
+    if ($column_name == $schema['primary key'][0]) {
+      continue;
+    }
+
+    // Skip the type field.
+    if ($table_name == $type_table and $column_name == $type_field) {
+      continue;
+    }
+
+    // Get the field defaults for this column.
+    $field_info = tripal_chado_add_bundle_fields_base_fields_defaults($table_name, $schema, $column_name);
+
+
+    // TODO: add in a call to drupal_alter to allow other modules to change
+    // the field settings.
+
+    // Determine if the field is required.
+    if (array_key_exists('not null', $details) and $details['not null'] === TRUE) {
+      $field_info['is_required'] = array_key_exists('default', $details) ? 0 : 1;
+    }
+
+    // If we don't have a field type then we don't need to create a field.
+    if (!$field_info['field_type']) {
+      // If we don't have a field type but it is required and doesn't have
+      // a default value then we are in trouble.
+      if ($field_info['is_required'] and !array_key_exists('default', $details)) {
+        throw new Exception(t('The %table.%field type, %type, is not yet supported for Entity fields, but it is required,',
+            array('%table' => $table_name, '%field' => $column_name, '%type' => $details['type'])));
+      }
+      continue;
+    }
+
+    // If this field is a foreign key field then we will have a custom field.
+    $is_fk = FALSE;
+    if (array_key_exists('foreign keys', $schema)) {
+      foreach ($schema['foreign keys'] as $remote_table => $fk_details) {
+        if (array_key_exists($column_name, $fk_details['columns'])) {
+          $is_fk = TRUE;
+        }
+      }
+    }
+
+    // Add the field to the bundle.
+    tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+  }
+}

+ 8 - 3
tripal_chado/includes/tripal_chado.term_storage.inc

@@ -23,7 +23,7 @@ function tripal_chado_vocab_get_term($namespace, $accession) {
     'accession'  => $accession,
     'name'       => '',
     'definition' => 'Term is undefined.',
-    'urlprefix'  => '',
+    'url'  => '',
     // The following are not required for the returned array but we'll
     // add these for convenience later when we look at the TripalTerm
     // objects and these will be there.
@@ -50,17 +50,22 @@ function tripal_chado_vocab_get_term($namespace, $accession) {
     return $empty_term;
   }
   $cvterm = chado_expand_var($cvterm, 'field', 'cvterm.definition');
-  return array(
+  $term = array(
     'namespace'  => $cvterm->dbxref_id->db_id->name,
     'accession'  => $cvterm->dbxref_id->accession,
     'name'       => $cvterm->name,
+    'url'        => '',
     'definition' => (isset($cvterm->definition)) ? $cvterm->definition : '',
-    'urlprefix'  => $cvterm->dbxref_id->db_id->urlprefix,
     // The following are not required for the returned array but we'll
     // add these for convenience later when we look at the TripalTerm
     // objects and these will be there.
     'cvterm'     => $cvterm,
   );
+  if ($cvterm->dbxref_id->db_id->urlprefix) {
+    $term['url'] = $cvterm->dbxref_id->db_id->urlprefix .
+      $cvterm->dbxref_id->db_id->name . ':' . $cvterm->dbxref_id->accession;
+  }
+  return $term;
 }
 
 /**

+ 12 - 1224
tripal_chado/tripal_chado.module

@@ -1,7 +1,10 @@
 <?php
 
-// APPLICATION PROGRAMMER INTERFACE -------------
-// Chado API
+//
+// APPLICATION PROGRAMMER INTERFACE
+//
+
+// Generic Chado API functions
 require_once "api/tripal_chado.api.inc";
 require_once 'api/tripal_chado.property.api.inc';
 require_once 'api/tripal_chado.query.api.inc';
@@ -12,6 +15,7 @@ require_once 'api/tripal_chado.mviews.api.inc';
 require_once 'api/tripal_chado.schema_v1.2.api.inc';
 require_once 'api/tripal_chado.schema_v1.11.api.inc';
 
+// Chado module specific API functions
 require_once 'api/modules/tripal_chado.analysis.api.inc';
 require_once 'api/modules/tripal_chado.contact.api.inc';
 require_once 'api/modules/tripal_chado.cv.api.inc';
@@ -21,10 +25,16 @@ require_once 'api/modules/tripal_chado.organism.api.inc';
 require_once 'api/modules/tripal_chado.pub.api.inc';
 require_once 'api/modules/tripal_chado.stock.api.inc';
 
+//
+// REQUIRED INCLUDE FILES
+//
+// These require files implement hooks and therefore must
+// ways be included when the module is interpreted.
 require_once "includes/tripal_chado.entity.inc";
 require_once "includes/tripal_chado.schema.inc";
 require_once "includes/tripal_chado.term_storage.inc";
 require_once "includes/tripal_chado.field_storage.inc";
+require_once "includes/tripal_chado.fields.inc";
 
 tripal_chado_set_globals();
 
@@ -488,614 +498,6 @@ function tripal_chado_permission() {
   );
 }
 
-/**
- * Implements hook_field_info().
- */
-function tripal_chado_field_info() {
-  $fields = array(
-    'organism_id' => array(
-      'label' => t('Organism'),
-      'description' => t('A field for specifying an organism.'),
-      'default_widget' => 'tripal_chado_organism_select_widget',
-      'default_formatter' => 'tripal_chado_organism_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'dbxref_id' => array(
-      'label' => t('Cross reference'),
-      'description' => t('This record can be cross referenced with a record in
-          another online database. This field is intended for the most prominent
-          reference.  At a minimum, the database and accession must be provided.'),
-      'default_widget' => 'tripal_chado_dbxref_id_widget',
-      'default_formatter' => 'tripal_chado_dbxref_id_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'residues' => array(
-      'label' => t('Residues'),
-      'description' => t('A field for managing nucleotide and protein residues.'),
-      'default_widget' => 'tripal_chado_residue_textarea_widget',
-      'default_formatter' => 'tripal_chado_residues_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'md5checksum' => array(
-      'label' => t('MD5 checksum'),
-      'description' => t('A field for generating MD5 checksum for a sequence.'),
-      'default_widget' => 'tripal_chado_md5checksum_checkbox_widget',
-      'default_formatter' => 'tripal_chado_md5checksum_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'seqlen' => array(
-      'label' => t('Sequence length'),
-      'description' => t('A field for calculating the length of a sequence.'),
-      'default_widget' => 'tripal_chado_seqlen_hidden_widget',
-      'default_formatter' => 'tripal_chado_seqlen_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    // The field provides a widget for adding new properties
-    // to an entity that is connected to a base table that has a prop table
-    // in Chado.
-    'kvproperty_adder' => array(
-      'label' => t('Add a Property Type'),
-      'description' => t('This record may have any number of properties. Use
-          this field to first add the type.'),
-      'default_widget' => 'tripal_chado_kvproperty_adder_widget',
-      //'default_formatter' => 'tripal_chado_kvproperty_adder_formatter',
-      'default_formatter' => 'hidden',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    // The field provides form elements for adding a property to an entity
-    // that in turn gets stored in a prop table of Chado (e.g. featureprop,
-    // stockprop, etc).
-    'kvproperty' => array(
-      'label' => t('Add a Property'),
-      'description' => t('Add details about this property.'),
-      'default_widget' => 'tripal_chado_kvproperty_widget',
-      'default_formatter' => 'tripal_chado_kvproperty_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-
-    // The field provides form elements for adding multiple dbxrefs to an
-    // entity that in turn get stored in a [base]_dbxref table of Chado
-    // (e.g. organism_dbxref, feature_dbxref).  This is different
-    // from the dbxref_id field as that is specific to a dbxref_id in
-    // a base table.
-    'dbxref' => array(
-      'label' => t('Cross references'),
-      'description' => t('This record can be cross referenced with a record in
-          another online database. This field is intended for one or more
-          references.  At a minimum, the database and accession must be provided.'),
-      'default_widget' => 'tripal_chado_dbxref_widget',
-      'default_formatter' => 'tripal_chado_dbxref_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    // The field provides a widget for adding new vocabularies for cvterm
-    // linker tables. This will allow cvterms to be grouped by vocabulary
-    // ('category').
-    'cvterm_class_adder' => array(
-      'label' => t('Add an Annotation Type'),
-      'description' => t('This record may have any number of types of
-          annotations. Use this field to first add the type.'),
-      'default_widget' => 'tripal_chado_cvterm_class_adder_widget',
-      //'default_formatter' => 'tripal_chado_cvterm_class_adder_formatter',
-      'default_formatter' => 'hidden',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    // The field provides form elements for adding multiple cvterms to an
-    // entity that in turn get stored in a [base]_cvterm table of Chado
-    // (e.g. feature_cvterm).
-    'cvterm' => array(
-      'label' => t('Annotations'),
-      'description' => t('This record can be annotated with terms
-          from other vocabularies.'),
-      'default_widget' => 'tripal_chado_cvterm_widget',
-      'default_formatter' => 'tripal_chado_cvterm_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-
-    'synonym' => array(
-      'label' => t('Synonyms'),
-      'description' => t('Adds an alternative name (synonym or alias) to this record.'),
-      'default_widget' => 'tripal_chado_synonym_widget',
-      'default_formatter' => 'tripal_chado_synonym_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-
-    'pub' => array(
-      'label' => t('Publications'),
-      'description' => t('Associates a publication (e.g. journal article, conference proceedings, book chapter, etc.) with this record.'),
-      'default_widget' => 'tripal_chado_pub_widget',
-      'default_formatter' => 'tripal_chado_pub_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-  );
-  return $fields;
-}
-
-/**
- * Implements hook_field_widget_info().
- */
-function tripal_chado_field_widget_info() {
-  return array(
-    'tripal_chado_organism_select_widget' => array(
-      'label' => t('Organism Select'),
-      'field types' => array('organism_id')
-    ),
-    'tripal_chado_dbxref_id_widget' => array(
-      'label' => t('Cross reference'),
-      'field types' => array('dbxref_id'),
-      'description' => t('This record can be cross referenced with a record in
-        another online database. This field is intended for the most
-        prominent reference.  At a minimum, the database and accession
-        must be provided.'),
-    ),
-    'tripal_chado_dbxref_widget' => array(
-      'label' => t('Cross references'),
-      'field types' => array('dbxref'),
-      'description' => t('This record can be cross referenced with a record
-        in another online database. This field is intended for the most
-        prominent reference.  At a minimum, the database and accession
-        must be provided.'),
-    ),
-    'tripal_chado_cvterm_class_adder_widget' => array(
-      'label' => t('Add an Annotation'),
-      'field types' => array('cvterm_class_adder'),
-    ),
-    'tripal_chado_cvterm_widget' => array(
-      'label' => t('Annotations'),
-      'field types' => array('cvterm'),
-      'description' => t('This record can be annotated with terms
-          from other vocabularies.'),
-    ),
-    'tripal_chado_md5checksum_checkbox_widget' => array(
-      'label' => t('MD5 Checksum Checkbox'),
-      'field types' => array('md5checksum'),
-    ),
-    'tripal_chado_residues_textarea_widget' => array(
-      'label' => t('Residues'),
-      'field types' => array('residues'),
-    ),
-    'tripal_chado_seqlen_hidden_widget' => array(
-      'label' => t('Sequence Length'),
-      'field types' => array('seqlen'),
-    ),
-    'tripal_chado_kvproperty_adder_widget' => array(
-      'label' => t('Add a Property'),
-      'field types' => array('kvproperty_adder'),
-    ),
-    'tripal_chado_kvproperty_widget' => array(
-      'label' => t('Property'),
-      'field types' => array('kvproperty'),
-    ),
-    'tripal_chado_synonym_widget' => array(
-      'label' => t('Synonyms'),
-      'field types' => array('synonym'),
-    ),
-    'tripal_chado_pub_widget' => array(
-      'label' => t('Publications'),
-      'field types' => array('pub'),
-    ),
-  );
-}
-/**
- * Implements hook_field_formatter_info().
- */
-function tripal_chado_field_formatter_info() {
-  return array(
-    'tripal_chado_organism_formatter' => array(
-      'label' => t('Organism'),
-      'field types' => array('organism_id')
-    ),
-    'tripal_chado_dbxref_id_formatter' => array(
-      'label' => t('Cross reference'),
-      'field types' => array('dbxref_id')
-    ),
-    'tripal_chado_dbxref_formatter' => array(
-      'label' => t('Cross references'),
-      'field types' => array('dbxref')
-    ),
-    'tripal_chado_cvterm_class_adder_formatter' => array(
-      'label' => t('Add an Annotation'),
-      'field types' => array('cvterm_class_adder')
-    ),
-    'tripal_chado_cvterm_formatter' => array(
-      'label' => t('Annotations'),
-      'field types' => array('cvterm')
-    ),
-    'tripal_chado_md5checksum_formatter' => array(
-      'label' => t('MD5 checksum'),
-      'field types' => array('md5checksum')
-    ),
-    'tripal_chado_residues_formatter' => array(
-      'label' => t('Residues'),
-      'field types' => array('residues')
-    ),
-    'tripal_chado_seqlen_formatter' => array(
-      'label' => t('Sequence length'),
-      'field types' => array('seqlen')
-    ),
-    'tripal_chado_kvproperty_adder_formatter' => array(
-      'label' => t('Add a Property'),
-      'field types' => array('kvproperty_adder')
-    ),
-    'tripal_chado_kvproperty_formatter' => array(
-      'label' => t('Property'),
-      'field types' => array('kvproperty')
-    ),
-    'tripal_chado_synonym_formatter' => array(
-      'label' => t('Synonyms'),
-      'field types' => array('synonym')
-    ),
-    'tripal_chado_pub_formatter' => array(
-      'label' => t('Publications'),
-      'field types' => array('pub')
-    ),
-  );
-}
-
-/**
- * Implements hook_field_widget_form_alter().
- */
-function tripal_chado_field_widget_form_alter(&$element, &$form_state, $context) {
-
-  if (array_key_exists('#field_name', $element)) {
-    $field_name = $element['#field_name'];
-    $matches = array();
-
-    if (preg_match('/(.+?)__(.+?)$/', $field_name, $matches)) {
-      $tablename = $matches[1];
-      $colname = $matches[2];
-      $schema = chado_get_schema($tablename);
-
-      // The timelastmodified field exists in many Chado tables.  We want
-      // the form element to update to the most recent time rather than the time
-      // in the database.
-      if ($colname == 'timelastmodified' and $schema['fields'][$colname]['type'] == 'datetime') {
-        // We want the default value for the field to be the current time.
-        $element['#default_value']['value'] = format_date(time(), 'custom', "Y-m-d H:i:s", 'UTC');
-        $element['#date_items']['value'] = $element['#default_value']['value'];
-      }
-      // We want the date combo fieldset to be collaspible so we will
-      // add our own theme_wrapper to replace the one added by the date
-      // module.
-      if (array_key_exists($colname, $schema['fields']) and $schema['fields'][$colname]['type'] == 'datetime') {
-        $element['#theme_wrappers'] = array('tripal_chado_date_combo');
-      }
-    }
-  }
-}
-
-
-/**
- * Implements hook_field_formatter_view().
- */
-function tripal_chado_field_formatter_view($entity_type, $entity, $field,
-  $instance, $langcode, $items, $display) {
-
-  $element = array();
-  switch ($display['type']) {
-    case 'tripal_chado_organism_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/organism_id');
-      tripal_chado_organism_select_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_dbxref_id_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/dbxref_id');
-      tripal_chado_dbxref_id_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_dbxref_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/dbxref');
-      tripal_chado_dbxref_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_cvterm_class_adder_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/cvterm_class_adder');
-      tripal_chado_cvterm_class_adder_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_cvterm_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/cvterm');
-      tripal_chado_cvterm_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_md5checksum_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/md5checksum');
-      tripal_chado_md5checksum_checkbox_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_residues_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/residues');
-      tripal_chado_residues_textarea_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_seqlen_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/seqlen');
-      tripal_chado_seqlen_hidden_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_kvproperty_adder_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/kvproperty_adder');
-      tripal_chado_kvproperty_adder_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_kvproperty_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/kvproperty');
-      tripal_chado_kvproperty_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_synonym_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/synonym');
-      tripal_chado_synonym_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-    case 'tripal_chado_pub_formatter':
-      module_load_include('inc', 'tripal_chado', 'includes/fields/pub');
-      tripal_chado_pub_formatter($element, $entity_type, $entity, $field,
-          $instance, $langcode, $items, $display);
-      break;
-  }
-  return $element;
-}
-
-/**
- * Implements hook_field_widget_form().
- */
-function tripal_chado_field_widget_form(&$form, &$form_state, $field,
-    $instance, $langcode, $items, $delta, $element) {
-
-  $widget = $element;
-  switch ($instance['widget']['type']) {
-    case 'tripal_chado_organism_select_widget':
-      // Make sure the include files get parsed now and for the form submits.
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/organism_id');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/organism_id');
-      // Update the widget with the new field.
-      tripal_chado_organism_select_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_dbxref_id_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/dbxref_id');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/dbxref_id');
-      tripal_chado_dbxref_id_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_dbxref_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/dbxref');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/dbxref');
-      tripal_chado_dbxref_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_cvterm_class_adder_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/cvterm_class_adder');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/cvterm_class_adder');
-      tripal_chado_cvterm_class_adder_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_cvterm_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/cvterm');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/cvterm');
-      tripal_chado_cvterm_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_md5checksum_checkbox_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/md5checksum');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/md5checksum');
-      tripal_chado_md5checksum_checkbox_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_residues_textarea_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/residues');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/residues');
-      tripal_chado_residues_textarea_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_seqlen_hidden_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/seqlen');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/seqlen');
-      tripal_chado_seqlen_hidden_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_kvproperty_adder_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/kvproperty_adder');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/kvproperty_adder');
-      tripal_chado_kvproperty_adder_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_kvproperty_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/kvproperty');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/kvproperty');
-      tripal_chado_kvproperty_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_synonym_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/synonym');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/synonym');
-      tripal_chado_synonym_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-    case 'tripal_chado_pub_widget':
-      form_load_include($form_state, 'inc', 'tripal_chado', 'includes/fields/pub');
-      module_load_include('inc', 'tripal_chado', 'includes/fields/pub');
-      tripal_chado_pub_widget($widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
-      break;
-  }
-  return $widget;
-}
-
-/**
- * Implements hook_form_FORM_ID_alter().
- *
- * The field_ui_display_overview_form is used for formatting the display
- * or layout of fields attached to an entity and shown on the entity view page.
- *
- * This function removes the cvterm class and property adder field as those are
- * really not meant for users to show or manage.
- */
-function tripal_chado_form_field_ui_display_overview_form_alter(&$form, &$form_state, $form_id) {
-  // Remove the kvproperty_addr field as it isn't ever displayed. It's just used
-  // on the add/edit form of an entity for adding new property fields.
-  $fields_names = element_children($form['fields']);
-  foreach ($fields_names as $field_name) {
-    $field_info = field_info_field($field_name);
-    if ($field_info['type'] == 'kvproperty_adder') {
-      unset($form['fields'][$field_name]);
-    }
-    if ($field_info['type'] == 'cvterm_class_adder') {
-      unset($form['fields'][$field_name]);
-    }
-  }
-}
-/**
- * Implements hook_form_FORM_ID_alter().
- *
- * The field_ui_field_overview_form is used for ordering and configuring the
- * fields attached to an entity.
- *
- * This function removes the property adder field as that is really not meant
- * for users to show or manage.
- */
-function tripal_chado_form_field_ui_field_overview_form_alter(&$form, &$form_state, $form_id) {
-  // Remove the kvproperty_addr field as it isn't ever displayed. It's just used
-  // on the add/edit form of an entity for adding new property fields.
-  $fields_names = element_children($form['fields']);
-  foreach ($fields_names as $field_name) {
-    $field_info = field_info_field($field_name);
-    if ($field_info['type'] == 'kvproperty_adder') {
-      unset($form['fields'][$field_name]);
-    }
-    if ($field_info['type'] == 'cvterm_class_adder') {
-      unset($form['fields'][$field_name]);
-    }
-  }
-}
-/**
- * Implements hook_field_is_empty().
- */
-function tripal_chado_field_is_empty($item, $field) {
-
-  // If there is no value field then the field is empty.
-  if (!array_key_exists('value', $item)) {
-    return TRUE;
-  }
-
-  // Iterate through all of the fields and if at least one has a value
-  // the field is not empty.
-  foreach ($item as $form_field_name => $value) {
-    if (isset($value) and $value != NULL and $value != '') {
-      return FALSE;
-    }
-  }
-
-  // Otherwise, the field is empty.
-  return TRUE;
-}
-
-/**
- * Returns the values of the field from the $form_state.
- */
-function tripal_chado_get_field_form_values($field_name, $form_state, $delta = 0, $child = NULL) {
-  $value = NULL;
-  // The form_state must have the 'values' key. If not then just return.
-  if (!array_key_exists('values', $form_state)) {
-    return $value;
-  }
-
-  // If the field name is not in the form_state['values'] then return.
-  if (!array_key_exists($field_name, $form_state['values'])) {
-    return $value;
-  }
-
-  // Iterate through the values looking for the field_name provided.
-  foreach ($form_state['values'][$field_name] as $langcode => $items) {
-    if (!array_key_exists($delta, $items)) {
-      continue;
-    }
-    $item = $items[$delta];
-    if ($child){
-      if(array_key_exists($child, $item) and $item[$child] != '') {
-        $value = $item[$child];
-      }
-    }
-    else {
-      $value = $item['value'];
-    }
-  }
-  return $value;
-}
-
-/**
- * Sets the values of the field from the $form_state.
- */
-function tripal_chado_set_field_form_values($field_name, &$form_state, $newvalue, $delta = 0, $child = NULL) {
-  // The form_state must have the 'values' key. If not then just return.
-  if (!array_key_exists('values', $form_state)) {
-    return FALSE;
-  }
-
-  // If the field name is not in the form_state['values'] then reutrn.
-  if (!array_key_exists($field_name, $form_state['values'])) {
-    return FALSE;
-  }
-
-  foreach ($form_state['values'][$field_name] as $langcode => $items) {
-    if ($child) {
-      $form_state['values'][$field_name][$langcode][$delta][$child] = $newvalue;
-    }
-    else {
-      $form_state['values'][$field_name][$langcode][$delta]['value'] = $newvalue;
-    }
-  }
-  return TRUE;
-}
-
 /**
  * Implements hook_theme().
  */
@@ -1143,622 +545,8 @@ function tripal_chado_theme($existing, $type, $theme, $path) {
   );
 }
 
-/**
- * Implements hook_add_bundle_fields().
- */
-function tripal_chado_add_bundle_fields($entity_type, $bundle, $term) {
-
-  $bundle_name = $bundle->name;
-
-  // This array will hold details that map the bundle to tables in Chado.
-  $bundle_data = array();
-
-  // Get the cvterm that corresponds to this TripalTerm object.
-  $vocab = entity_load('TripalVocab', array($term->vocab_id));
-  $vocab = reset($vocab);
-  $match = array(
-    'dbxref_id' => array(
-      'db_id' => array(
-        'name' => $vocab->namespace,
-      ),
-      'accession' => $term->accession
-    ),
-  );
-  $cvterm = chado_generate_var('cvterm', $match);
-
-  // The organism table does not have a type_id so we won't ever find
-  // a record for it in the tripal_cv_defaults table.
-  if ($cvterm->name == 'organism') {
-    $bundle_data = array(
-      'cv_id' => $cvterm->cv_id->cv_id,
-      'cvterm_id' => $cvterm->cvterm_id,
-      'data_table' => 'organism',
-      'type_table' => 'organism',
-      'field' =>  '',
-    );
-  }
-  // The analysis table does not have a type_id so we won't ever find
-  // a record for it in the tripalcv_defaults table.
-  else if ($cvterm->name == 'analysis') {
-    $bundle_data = array(
-      'cv_id' => $cvterm->cv_id->cv_id,
-      'cvterm_id' => $cvterm->cvterm_id,
-      'data_table' => 'analysis',
-      'type_table' => 'analysis',
-      'field' =>  '',
-    );
-  }
-  else if ($cvterm->name == 'project') {
-    $bundle_data = array(
-      'cv_id' => $cvterm->cv_id->cv_id,
-      'cvterm_id' => $cvterm->cvterm_id,
-      'data_table' => 'project',
-      'type_table' => 'project',
-      'field' =>  '',
-    );
-  }
-  else {
-    // TODO: WHAT TO DO IF A VOCABULARY IS USED AS A DEFAULT FOR MULTIPLE
-    // TABLES.
-    // Look to see if this vocabulary is used as a default for any table.
-    $default = db_select('tripal_cv_defaults', 't')
-      ->fields('t')
-      ->condition('cv_id', $cvterm->cv_id->cv_id)
-      ->execute()
-      ->fetchObject();
-    if ($default) {
-      $bundle_data = array(
-        'cv_id' => $cvterm->cv_id->cv_id,
-        'cvterm_id' => $cvterm->cvterm_id,
-        'data_table' => $default->table_name,
-        'type_table' => $default->table_name,
-        'field' =>  $default->field_name,
-      );
-    }
-  }
-
-  // Save the mapping information so that we can reuse it when we need to
-  // look things up for later for an entity
-  tripal_set_bundle_variable('chado_cvterm_id', $bundle->id, $bundle_data['cvterm_id']);
-  tripal_set_bundle_variable('chado_table', $bundle->id, $bundle_data['data_table']);
-  tripal_set_bundle_variable('chado_column', $bundle->id, $bundle_data['field']);
-
-  //////////////////////////////////////////////////////////////////////////////
-  // ADD FIELDS TO BUNDLE
-  ////////////////////////////////////////////////////////////////////////////
-
-  ////
-  //
-  // Base table fields.
-  //
-  // Adds the fields for the base table to the entity.  Adds fields
-  // for all columns including FK fields.  Excludes primary key and the
-  // type_id field (that's inherent in the bundle).
-  tripal_chado_add_bundle_base_fields($entity_type, $bundle_name, $bundle_data);
-
-  ////
-  //
-  // Property table fields.
-  //
-  // Check to see if there are any property tables with FKs to this
-  // base table. If so, add the fields for that type of table.
-  $prop_table = $bundle_data['data_table'] . 'prop';
-  if (chado_table_exists($prop_table)) {
-    tripal_chado_add_bundle_kvproperty_adder_field($entity_type, $bundle_name, $prop_table, $bundle_data['data_table']);
-  }
-
-  ////
-  //
-  // Dbxref table fields.
-  //
-  // Check to see if there are any dbxref tables with FKs to this
-  // base table. If so, add the fields for that type of table.
-  $dbxref_table = $bundle_data['data_table'] . '_dbxref';
-  if (chado_table_exists($dbxref_table)) {
-    tripal_chado_add_bundle_dbxref_field($entity_type, $bundle_name, $dbxref_table, $bundle_data['data_table']);
-  }
-
-  ////
-  //
-  // Cvterm table fields.
-  //
-  // Check to see if there are any cvterm tables with FKs to this
-  // base table. If so, add the fields for that type of table.
-  $cvterm_table = $bundle_data['data_table'] . '_cvterm';
-  if (chado_table_exists($cvterm_table)) {
-    tripal_chado_add_bundle_cvterm_class_adder_field($entity_type, $bundle_name, $cvterm_table, $bundle_data['data_table']);
-  }
-
-
-  ////
-  //
-  // Synonym table fields.
-  //
-  // Check to see if there are any synonym tables with FKs to this
-  // base table. If so, add the fields for that type of table.
-  $syn_table = $bundle_data['data_table'] . '_synonym';
-  if (chado_table_exists($syn_table)) {
-    tripal_chado_add_bundle_synonym_field($entity_type, $bundle_name, $syn_table, $bundle_data['data_table']);
-  }
-
-  ////
-  //
-  // Pub table fields.
-  //
-  // Check to see if there are any pub tables with FKs to this
-  // base table. If so, add the fields for that type of table.
-  $pub_table = $bundle_data['data_table'] . '_pub';
-  if (chado_table_exists($pub_table)) {
-    tripal_chado_add_bundle_pub_field($entity_type, $bundle_name, $pub_table, $bundle_data['data_table']);
-  }
-}
-
-/**
- * Adds the fields for managing xrefs that are stored in a [base]_dbxref table.
- *
- * @param $entity_type
- * @param $bundle_name
- * @param $base_table
- * @param $dbxref_table
- */
-function tripal_chado_add_bundle_dbxref_field($entity_type_name, $bundle_name, $dbxref_table, $base_table) {
-  // We already have a dbxref_id field.
-  $field_name = $dbxref_table;
-  $schema = chado_get_schema($dbxref_table);
-  $pkey = $schema['primary key'][0];
-
-  // Initialize the field array.
-  $field_info = array(
-    'field_type' => 'dbxref',
-    'widget_type' => 'tripal_fields_dbxfref_widget',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Cross References',
-    'is_required' => 0,
-    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-    'storage' => 'field_chado_storage',
-    'field_settings' => array(
-      // The Chado table that this field maps to.
-      'chado_table' => $dbxref_table,
-      // The column in the chado table that this field maps to.
-      'chado_column' => $pkey,
-      // The base table that this field is connected to.
-      'base_table' => $base_table,
-      'semantic_web' => array(
-        // The type is the term from a vocabulary that desribes this field..
-        'type' => '',
-        // The namepsace for the vocabulary (e.g. 'foaf').
-        'ns' => '',
-        // The URL for the namespace.  It must be that the type can be
-        // appended to the URL.
-        'nsurl' => '',
-      ),
-    ),
-  );
-
-  // If the base table has a 'dbxref_id' then change the label to
-  // indicate these are secondary cross references.
-  $schema = chado_get_schema($base_table);
-  if (array_key_exists('dbxref_id', $schema['fields'])) {
-    $field_info['label'] = 'Secondary Cross References';
-  }
-  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
-}
-/**
- * Adds the fields for managing xrefs that are stored in a [base]_dbxref table.
- *
- * @param $entity_type
- * @param $bundle_name
- * @param $base_table
- * @param $dbxref_table
- */
-function tripal_chado_add_bundle_synonym_field($entity_type_name, $bundle_name, $syn_table, $base_table) {
-  // We already have a dbxref_id field.
-  $field_name = $syn_table;
-  $schema = chado_get_schema($syn_table);
-  $pkey = $schema['primary key'][0];
-
-  // Initialize the field array.
-  $field_info = array(
-    'field_type' => 'synonym',
-    'widget_type' => 'tripal_fields_synonym_widget',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Synonyms',
-    'is_required' => 0,
-    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-    'storage' => 'field_chado_storage',
-    'field_settings' => array(
-      // The Chado table that this field maps to.
-      'chado_table' => $syn_table,
-      // The column in the chado table that this field maps to.
-      'chado_column' => $pkey,
-      // The base table that this field is connected to.
-      'base_table' => $base_table,
-      'semantic_web' => array(
-        // The type is the term from a vocabulary that desribes this field..
-        'type' => '',
-        // The namepsace for the vocabulary (e.g. 'foaf').
-        'ns' => '',
-        // The URL for the namespace.  It must be that the type can be
-        // appended to the URL.
-        'nsurl' => '',
-      ),
-    ),
-  );
-
-  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
-}
-/**
- * Adds the fields for managing xrefs that are stored in a [base]_dbxref table.
- *
- * @param $entity_type
- * @param $bundle_name
- * @param $base_table
- * @param $dbxref_table
- */
-function tripal_chado_add_bundle_pub_field($entity_type_name, $bundle_name, $pub_table, $base_table) {
-  // We already have a dbxref_id field.
-  $field_name = $pub_table;
-  $schema = chado_get_schema($pub_table);
-  $pkey = $schema['primary key'][0];
-
-  // Initialize the field array.
-  $field_info = array(
-    'field_type' => 'pub',
-    'widget_type' => 'tripal_fields_pub_widget',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Publications',
-    'is_required' => 0,
-    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-    'storage' => 'field_chado_storage',
-    'field_settings' => array(
-      // The Chado table that this field maps to.
-      'chado_table' => $pub_table,
-      // The column in the chado table that this field maps to.
-      'chado_column' => $pkey,
-      // The base table that this field is connected to.
-      'base_table' => $base_table,
-      'semantic_web' => array(
-        // The type is the term from a vocabulary that desribes this field..
-        'type' => '',
-        // The namepsace for the vocabulary (e.g. 'foaf').
-        'ns' => '',
-        // The URL for the namespace.  It must be that the type can be
-        // appended to the URL.
-        'nsurl' => '',
-      ),
-    ),
-  );
-
-  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
-}
-/**
- * Adds the fields for managing properties that are stored in a prop table.
- *
- * @param $entity_type_name
- * @param $bundle_name
- * @param $kv_table
- */
-function tripal_chado_add_bundle_kvproperty_adder_field($entity_type_name, $bundle_name, $kv_table, $base_table) {
-  $field_name = $kv_table;
-
-  // Initialize the field array.
-  $field_info = array(
-    'field_type' => 'kvproperty_adder',
-    'widget_type' => 'tripal_fields_kvproperty_adder_widget',
-    'field_settings' => array(
-      'base_table' => $base_table,
-    ),
-    'storage' => 'field_chado_storage',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Additional Properties',
-    'is_required' => 0,
-  );
-  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
-}
-/**
- * Adds the fields for managing properties that are stored in a prop table.
- *
- * @param $entity_type_name
- * @param $bundle_name
- * @param $kv_table
- */
-function tripal_chado_add_bundle_cvterm_class_adder_field($entity_type_name, $bundle_name, $cvterm_table, $base_table) {
-  // First add a generic property field so that users can add new property types.
-  $field_name = $cvterm_table;
-
-  // Initialize the field array.
-  $field_info = array(
-    'field_type' => 'cvterm_class_adder',
-    'widget_type' => 'tripal_fields_cvterm_class_adder_widget',
-    'field_settings' => array(
-      'base_table' => $base_table,
-    ),
-    'storage' => 'field_chado_storage',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Additional Annotation Types',
-    'is_required' => 0,
-  );
-  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
-}
-/**
- * Adds the fields for the base table to the entity.
- */
-function tripal_chado_add_bundle_base_fields($entity_type_name, $bundle_name, $bundle_data) {
-
-  $table_name = $bundle_data['data_table'];
-  $type_table = $bundle_data['type_table'];
-  $type_field = $bundle_data['field'];
 
-  // Iterate through the columns of the table and see if fields have been
-  // created for each one. If not, then create them.
-  $schema = chado_get_schema($table_name);
-  $columns = $schema['fields'];
-  foreach ($columns as $column_name => $details) {
-    $field_name = $table_name . '__' . $column_name;
-
-    // Skip the primary key field.
-    if ($column_name == $schema['primary key'][0]) {
-      continue;
-    }
 
-    // Skip the type field.
-    if ($table_name == $type_table and $column_name == $type_field) {
-      continue;
-    }
-
-    // Get the field defaults for this column.
-    $field_info = tripal_chado_get_table_column_field_default($table_name, $schema, $column_name);
-
-
-    // TODO: add in a call to drupal_alter to allow other modules to change
-    // the field settings.
-
-    // Determine if the field is required.
-    if (array_key_exists('not null', $details) and $details['not null'] === TRUE) {
-      $field_info['is_required'] = array_key_exists('default', $details) ? 0 : 1;
-    }
-
-    // If we don't have a field type then we don't need to create a field.
-    if (!$field_info['field_type']) {
-      // If we don't have a field type but it is required and doesn't have
-      // a default value then we are in trouble.
-      if ($field_info['is_required'] and !array_key_exists('default', $details)) {
-        throw new Exception(t('The %table.%field type, %type, is not yet supported for Entity fields, but it is required,',
-            array('%table' => $table_name, '%field' => $column_name, '%type' => $details['type'])));
-      }
-      continue;
-    }
-
-    // If this field is a foreign key field then we will have a custom field.
-    $is_fk = FALSE;
-    if (array_key_exists('foreign keys', $schema)) {
-      foreach ($schema['foreign keys'] as $remote_table => $fk_details) {
-        if (array_key_exists($column_name, $fk_details['columns'])) {
-          $is_fk = TRUE;
-        }
-      }
-    }
-
-    // Add the field to the bundle.
-    tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
-  }
-}
-
-/**
- * Returns a $field_info array for a field based on a database column.
- *
- */
-function tripal_chado_get_table_column_field_default($table_name, $schema, $column_name) {
-  $details = $schema['fields'][$column_name];
-
-  // Create an array with information about this field.
-  $field = array(
-    'field_type' => '',
-    'widget_type' => '',
-    'description' => '',
-    'label' => ucwords(preg_replace('/_/', ' ', $column_name)),
-    'is_required' => 0,
-    'storage' => 'field_chado_storage',
-    'widget_settings' => array(
-      'display_label' => 1
-    ),
-    'field_settings' => array(
-      // The table in Chado where this field maps to.
-      'chado_table' => $table_name,
-      // The column in the Chado table that this field maps to.
-      'chado_column' => $column_name,
-      'semantic_web' => array(
-        // The type is the term from a vocabulary that desribes this field..
-        'type' => '',
-        // The namepsace for the vocabulary (e.g. 'foaf').
-        'ns' => '',
-        // The URL for the namespace.  It must be that the type can be
-        // appended to the URL.
-        'nsurl' => '',
-      ),
-    ),
-  );
-
-  // Alter the field info array depending on the column details.
-  switch($details['type']) {
-    case 'char':
-      $field['field_type'] = 'text';
-      $field['widget_type'] = 'text_textfield';
-      $field['field_settings']['max_length'] = $details['length'];
-      break;
-    case 'varchar':
-      $field['field_type'] = 'text';
-      $field['widget_type'] = 'text_textfield';
-      $field['field_settings']['max_length'] = $details['length'];
-      break;
-    case 'text':
-      $field['field_type'] = 'text';
-      $field['widget_type'] = 'text_textarea';
-      $field['field_settings']['max_length'] = 17179869184;
-      $field['field_settings']['text_processing'] = 1;
-      $field['format'] = filter_default_format();
-      break;
-    case 'blob':
-      // not sure how to support a blob field.
-      continue;
-      break;
-    case 'int':
-      $field['field_type'] = 'number_integer';
-      $field['widget_type'] = 'number';
-      break;
-    case 'float':
-      $field['field_type'] = 'number_float';
-      $field['widget_type'] = 'number';
-      $field['field_settings']['precision'] = 10;
-      $field['field_settings']['scale'] = 2;
-      $field['field_settings']['decimal_separator'] = '.';
-      break;
-    case 'numeric':
-      $field['field_type'] = 'number_decimal';
-      $field['widget_type'] = 'number';
-      break;
-    case 'serial':
-      // Serial fields are most likely not needed as a field.
-      break;
-    case 'boolean':
-      $field['field_type'] = 'list_boolean';
-      $field['widget_type'] = 'options_onoff';
-      $field['field_settings']['allowed_values'] = array(0 => "No", 1 => "Yes");
-      break;
-    case 'datetime':
-      // Use the Drupal Date and Date API to create the field/widget
-      $field['field_type'] = 'datetime';
-      $field['widget_type'] = 'date_select';
-      $field['widget_settings']['increment'] = 1;
-      $field['widget_settings']['tz_handling'] = 'none';
-      $field['widget_settings']['collapsible'] = TRUE;
-
-      // TODO: Add settings so that the minutes increment by 1.
-      // And turn off the timezone, as the Chado field doesn't support it.
-      break;
-  }
-
-  // Set some default semantic web information
-  if ($column_name == 'name') {
-    $field['field_settings']['semantic_web']['type'] = 'name';
-    $field['field_settings']['semantic_web']['ns'] = 'foaf';
-    $field['field_settings']['semantic_web']['nsurl'] = 'http://xmlns.com/foaf/0.1/';
-  }
-  if ($column_name == 'description' or $column_name == 'definition' or
-      $column_name == 'comment') {
-    $field['field_settings']['semantic_web']['type'] = 'description';
-    $field['field_settings']['semantic_web']['ns'] = 'hydra';
-    $field['field_settings']['semantic_web']['nsurl'] = 'http://www.w3.org/ns/hydra/core#';
-  }
-
-  //
-  // GENERIC COLUMNS
-  //
-  if ($field['field_settings']['chado_column'] =='organism_id') {
-    $field['field_type'] = 'organism_id';
-    $field['widget_type'] = 'tripal_chado_organism_select_widget';
-    $field['label'] = 'Organism';
-    $field['description'] = 'Select an organism.';
-  }
-  elseif ($field['field_settings']['chado_column'] =='dbxref_id') {
-    $field['field_type'] = 'dbxref_id';
-    $field['widget_type'] = 'tripal_chado_primary_dbxref_widget';
-    $field['label'] = 'Cross Reference';
-    $field['description'] = 'This record can be cross referenced with a ' .
-      'record in another online database. The primary reference is for the ' .
-      'most prominent reference.  At a minimum, the database and accession ' .
-      'must be provided.  To remove a set reference, change the database ' .
-      'field to "Select a Database".';
-  }
-  elseif ($field['label'] == 'Timeaccessioned') {
-    $field['label'] = 'Time Accessioned';
-    $field['description'] = 'Please enter the time that this record was first added to the database.';
-  }
-  elseif ($field['label'] == 'Timelastmodified') {
-    $field['label'] = 'Time Last Modified';
-    $field['description'] = 'Please enter the time that this record was last modified. The default is the current time.';
-  }
-  //
-  // ORGANISM TABLE
-  //
-  elseif ($field['field_settings']['chado_table'] == 'organism' and $field['field_settings']['chado_column'] == 'comment') {
-    $field['label'] = 'Description';
-  }
-  //
-  // FEATURE TABLE
-  //
-  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'uniquename') {
-    $field['field_type'] = 'text';
-    $field['widget_type'] = 'text_textfield';
-    $field['field_settings']['text_processing'] = 0;
-    $field['field_settings']['semantic_web']['type'] = 'name';
-    $field['field_settings']['semantic_web']['ns'] = 'foaf';
-    $field['field_settings']['semantic_web']['nsurl'] = 'http://xmlns.com/foaf/0.1/';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'md5checksum') {
-    $field['field_type'] = 'md5checksum';
-    $field['widget_type'] = 'tripal_chado_md5checksum_checkbox_widget';
-    $field['label'] = 'MD5 Checksum';
-    $field['description'] = 'Generate an MD5 checksum for the sequence.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'seqlen') {
-    $field['field_type'] = 'seqlen';
-    $field['widget_type'] = 'tripal_chado_seqlen_hidden_widget';
-    $field['label'] = 'Seqlen';
-    $field['description'] = 'The length of the residues.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'residues') {
-    $field['field_type'] = 'residues';
-    $field['widget_type'] = 'tripal_chado_residues_textarea_widget';
-    $field['label'] = 'Residues';
-    $field['description'] = 'Please provide an IUPAC compatible residues for this feature. Spaces and new lines are allowed.';
-  }
-  //
-  // ANALYSIS TABLE
-  //
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'program') {
-    $field['field_settings']['semantic_web']['type'] = 'SoftwareApplication';
-    $field['field_settings']['semantic_web']['ns'] = 'schema';
-    $field['field_settings']['semantic_web']['nsurl'] = 'https://schema.org/';
-    $field['description'] = 'The program name (e.g. blastx, blastp, sim4, genscan. If the analysis was not derived from a software package then provide a very brief description of the pipeline, workflow or method.';
-    $field['label'] = 'Program, Pipeline, Workflow or Method Name.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourceuri') {
-    $field['field_type'] = 'text';
-    $field['widget_type'] = 'text_textfield';
-    $field['field_settings']['text_processing'] = 0;
-    $field['label'] = 'Source URL';
-    $field['description'] = 'The URL where the original source data was derived.  Ideally, this should link to the page where more information about the source data can be found.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourcename') {
-    $field['label'] = 'Source Name';
-    $field['description'] = 'The name of the source data. This could be a file name, data set or a small description for how the data was collected. For long descriptions use the larger description field.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'sourceversion') {
-    $field['label'] = 'Source Version';
-    $field['description'] = 'If hte source data set has a version include it here.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'algorithm') {
-    $field['label'] = 'Source Version';
-    $field['description'] = 'The name of the algorithm used to produce the dataset if different from the program.';
-  }
-  elseif ($field['field_settings']['chado_table'] == 'analysis' and $field['field_settings']['chado_column'] == 'programversion') {
-    $field['label'] = 'Program Version';
-    $field['description'] = 'The version of the program used to perform this analysis. (e.g. TBLASTX 2.0MP-WashU [09-Nov-2000]. Enter "n/a" if no version is available or applicable.';
-  }
-  //
-  // PROJECT TABLE
-  //
-  elseif ($field['field_settings']['chado_table'] == 'project' and $field['field_settings']['chado_column'] == 'description') {
-    $field['label'] = 'Short Description';
-  }
-  return $field;
-}
 
 /**
  * Implements hook_exclude_type_by_default()

+ 115 - 8
tripal_ws/includes/tripal_ws.rest.inc

@@ -113,9 +113,11 @@ function tripal_ws_handle_vocab_service($api_url, &$response, $ws_args) {
   }
   // If we don't have a $namespace then show a paged list of terms.
   else if ($namespace and !$accession) {
+    tripal_ws_get_vocab($api_url, $response, $ws_args, $namespace);
   }
   // If we have a content type and an entity ID then show the entity
-  else {
+  else if ($namespace and $accession) {
+    tripal_ws_get_term($api_url, $response, $ws_args, $namespace, $accession);
   }
 }
 
@@ -138,11 +140,22 @@ function tripal_ws_get_vocabs($api_url, &$response) {
   $response['label'] = 'Content Types';
   $response['member'] = array();
 
-  // TODO: determine how to get the list of in-house terms that are used
-  // on the site.  This should really only include terms that are used
-  // as TripalEntity bundle types and that aren't part of another published
-  // vocabulary.
-
+  $vocabs = db_select('tripal_vocab', 'tv')
+    ->fields('tv')
+    ->execute();
+  // Iterate through the vocabularies and add an entry in the collection.
+  $i = 0;
+  while ($vocab = $vocabs->fetchObject()) {
+    $term =
+    // Add the bundle as a content type.
+    $response['member'][] = array(
+      '@id' => $api_url . '/vocab/' . urlencode($vocab->namespace),
+      '@type' => 'vocabulary',
+      'namespace' => $vocab->namespace,
+    );
+    $i++;
+  }
+  $response['totalItems'] = $i;
 
   //$response['totalItems'] = $i;
 
@@ -153,6 +166,100 @@ function tripal_ws_get_vocabs($api_url, &$response) {
   $response['@context']['label'] = 'rdfs:label';
   $response['@context']['description'] = 'hydra:description';
 }
+
+/**
+ *
+ * @param $api_url
+ * @param $response
+ * @param $ws_args
+ */
+function tripal_ws_get_vocab($api_url, &$response, $ws_args, $namespace) {
+
+  // First, add the vocabularies used into the @context section.
+  $response['@context']['rdfs'] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
+  $response['@context']['hydra'] = 'http://www.w3.org/ns/hydra/core#';
+  $response['@context']['schema'] = 'https://schema.org/';
+
+  // Next add in the ID for tihs resource.
+  $response['@id'] = $api_url . '/vocab/' . $namespace;
+
+  // Get the vocabulary
+  $vocab = tripal_load_vocab_entity(array('namespace' => $namespace));
+
+  // Start the list.
+  $response['@type'] = 'Collection';
+  $response['totalItems'] = 0;
+  $response['label'] = $namespace . " vocabulary collection";
+  $response['comment'] = 'The following list of terms may not be the full ' .
+    'list for the vocabulary.  The terms listed here are only those ' .
+    'that have associated content on this site.';
+
+  // Get the list of terms for this vocab.
+  $query = db_select('tripal_term', 'tt')
+    ->fields('tt', array('id'))
+    ->condition('vocab_id', $vocab->id)
+    ->orderBy('accession', 'DESC');
+
+  // Iterate through the entities and add them to the list.
+  $terms = $query->execute();
+  $i = 0;
+  while($term = $terms->fetchObject()) {
+    $term = tripal_load_term_entity(array('term_id' => $term->id));
+    $response['member'][] = array(
+      '@id' => $api_url . '/vocab/' . urlencode($namespace) . '/' .  urlencode($term->accession),
+      '@type' => 'vocabulary_term',
+      'namespace' => $vocab->namespace,
+      'accession' => $term->accession,
+      'name' => $term->name,
+      'definition' => $term->definition,
+    );
+    $i++;
+  }
+  $response['totalItems'] = $i;
+
+  // Lastly, add in the terms used into the @context section.
+  $response['@context']['Collection'] = 'hydra:Collection';
+  $response['@context']['totalItems'] = 'hydra:totalItems';
+  $response['@context']['member'] = 'hydra:member';
+  $response['@context']['label'] = 'rdfs:label';
+  $response['@context']['comment'] = 'rdfs:comment';
+  $response['@context']['itemPage'] = 'schema:itemPage';
+
+}
+
+/**
+ *
+ * @param $api_url
+ * @param $response
+ * @param $ws_args
+ */
+function tripal_ws_get_term($api_url, &$response, $ws_args, $namespace, $accession) {
+
+  // First, add the vocabularies used into the @context section.
+  $response['@context']['rdfs'] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
+  $response['@context']['hydra'] = 'http://www.w3.org/ns/hydra/core#';
+  $response['@context']['schema'] = 'https://schema.org/';
+
+  // Get the term.
+  $term = tripal_load_term_entity(array('namespace' => $namespace, 'accession' => $accession));
+
+  // Next add in the ID and Type for this resources.
+  $response['@id'] = $api_url . '/vocab/' . urlencode($namespace) . '/' . urlencode($accession);
+  $response['@type'] = 'vocabulary_term';
+  $response['label'] = $term->name;
+  $response['namespace'] = $namespace;
+  $response['accession'] = $accession;
+  $response['name'] = $term->name;
+  $response['definition'] = $term->definition;
+
+  if ($term->url) {
+    $response['URL'] = $term->url;
+  }
+
+  // Lastly, add in the terms used into the @context section.
+  $response['@context']['label'] = 'rdfs:label';
+  $response['@context']['itemPage'] = 'schema:itemPage';
+}
 /**
  * Provides a collection (list) of all of the content types.
  *
@@ -205,7 +312,7 @@ function tripal_ws_get_content_types($api_url, &$response) {
     }
     // Add the bundle as a content type.
     $response['member'][] = array(
-      '@id' => $api_url . '/content/' . $bundle->label,
+      '@id' => $api_url . '/content/' . urlencode($bundle->label),
       '@type' => $vocab->namespace . ':' . $term->accession,
       'label' => $bundle->label,
       'description' => $description,
@@ -273,7 +380,7 @@ function tripal_ws_get_content_type($api_url, &$response, $ws_args, $ctype) {
     $entities = entity_load('TripalEntity', array_keys($results['TripalEntity']));
     foreach ($entities as $entity) {
       $response['member'][] = array(
-        '@id' => $api_url . '/content/' . $ctype . '/' .  $entity->id,
+        '@id' => $api_url . '/content/' . urlencode($ctype) . '/' .  $entity->id,
         '@type' => $vocab->namespace . ':' . $term->accession,
         'label' => $entity->title,
         'itemPage' => url('/bio-data/' . $entity->id, array('absolute' => TRUE)),