Răsfoiți Sursa

Merge branch 'new_classes' into 7.x-3.x

Stephen Ficklin 8 ani în urmă
părinte
comite
9dea5cbfa7
50 a modificat fișierele cu 2012 adăugiri și 909 ștergeri
  1. 1 225
      tripal/api/tripal.entities.api.inc
  2. 70 11
      tripal/api/tripal.fields.api.inc
  3. 215 0
      tripal/api/tripal.terms.api.inc
  4. 12 1
      tripal/includes/TripalBundleController.inc
  5. 1 3
      tripal/includes/TripalEntityController.inc
  6. 101 380
      tripal/includes/TripalField.inc
  7. 148 0
      tripal/includes/TripalFieldFormatter.inc
  8. 167 0
      tripal/includes/TripalFieldWidget.inc
  9. 79 0
      tripal/includes/TripalFields/rdfs__type.inc
  10. 24 0
      tripal/includes/TripalFields/rdfs__type_formatter.inc
  11. 23 0
      tripal/includes/TripalFields/rdfs__type_widget.inc
  12. 17 2
      tripal/includes/TripalTerm.inc
  13. 3 3
      tripal/includes/tripal.entity.inc
  14. 3 1
      tripal/includes/tripal.field_storage.inc
  15. 228 138
      tripal/includes/tripal.fields.inc
  16. 2 0
      tripal/tripal.install
  17. 15 0
      tripal/tripal.module
  18. 2 2
      tripal_chado/includes/TripalFields.old/chado_base__dbxref_id.inc
  19. 1 2
      tripal_chado/includes/TripalFields.old/chado_base__organism_id.inc
  20. 0 0
      tripal_chado/includes/TripalFields.old/chado_feature__md5checksum.inc
  21. 0 0
      tripal_chado/includes/TripalFields.old/chado_feature__residues.inc
  22. 0 0
      tripal_chado/includes/TripalFields.old/chado_feature__seqlen.inc
  23. 0 0
      tripal_chado/includes/TripalFields.old/chado_gene__transcripts.inc
  24. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__contact.inc
  25. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__cvterm.inc
  26. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__cvterm_adder.inc
  27. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__dbxref.inc
  28. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__expression.inc
  29. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__featureloc.inc
  30. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__featurepos.inc
  31. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__genotype.inc
  32. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__phenotype.inc
  33. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__prop.inc
  34. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__prop_adder.inc
  35. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__pub.inc
  36. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__relationship.inc
  37. 0 0
      tripal_chado/includes/TripalFields.old/chado_linker__synonym.inc
  38. 0 0
      tripal_chado/includes/TripalFields.old/chado_organism__type_id.inc
  39. 149 0
      tripal_chado/includes/TripalFields/data__accession.inc
  40. 28 0
      tripal_chado/includes/TripalFields/data__accession_formatter.inc
  41. 227 0
      tripal_chado/includes/TripalFields/data__accession_widget.inc
  42. 194 0
      tripal_chado/includes/TripalFields/obi__organism.inc
  43. 33 0
      tripal_chado/includes/TripalFields/obi__organism_formatter.inc
  44. 46 0
      tripal_chado/includes/TripalFields/obi__organism_widget.inc
  45. 7 18
      tripal_chado/includes/tripal_chado.entity.inc
  46. 3 3
      tripal_chado/includes/tripal_chado.field_storage.inc
  47. 108 56
      tripal_chado/includes/tripal_chado.fields.inc
  48. 28 28
      tripal_chado/includes/tripal_chado.setup.inc
  49. 41 0
      tripal_chado/includes/tripal_chado.vocab_storage.inc
  50. 36 36
      tripal_chado/tripal_chado.module

+ 1 - 225
tripal/api/tripal.entities.api.inc

@@ -243,59 +243,11 @@ function tripal_create_bundle($vocabulary, $accession, $term_name, &$error = '')
     // Get the bundle object.
     $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
 
-    // Get the list of fields created by Tripal modules and
-    // create them if they don't already exist.
-    foreach (module_implements('create_tripalfields') as $module) {
-      $function = $module . '_create_tripalfields';
-      if (function_exists($function)) {
-        $fields = $function('TripalEntity', $bundle);
-        if (!$fields){
-          continue;
-        }
-        foreach ($fields as $field_name => $info) {
-          $field_type = $info['type'];
-
-          // If the field already exists then skip it.
-          $field = field_info_field($info['field_name']);
-          if ($field) {
-            continue;
-          }
-          // Create the field.
-          $field = field_create_field($info);
-          if (!$field) {
-            tripal_set_message(t("Could not create new field: %field.",
-              array('%field' =>  $info['field_name'])), TRIPAL_ERROR);
-          }
-        }
-      }
-    }
-
-    // Now get the list of field instances to add to the bundle.
-    foreach (module_implements('create_tripalfield_instance') as $module) {
-      $function = $module . '_create_tripalfield_instance';
-      if (function_exists($function)) {
-        $fields = $function('TripalEntity', $bundle);
-        if (!$fields){
-          continue;
-        }
-        foreach ($fields as $field_name => $info) {
-          // If the field is already attached to this bundle then skip it.
-          $field = field_info_field($info['field_name']);
-          if ($field and array_key_exists('bundles', $field) and
-              array_key_exists('TripalEntity', $field['bundles']) and
-              in_array($bundle_name, $field['bundles']['TripalEntity'])) {
-            continue;
-          }
-          // Create the field instance.
-          $instance = field_create_instance($info);
-        }
-      }
-    }
   }
   catch (Exception $e) {
     $transaction->rollback();
     $error = _drupal_decode_exception($e);
-    drupal_set_message(t("Failed to create content type': %message",
+    drupal_set_message(t("Failed to create content type: %message.",
         array('%message' => $error['!message'])), 'error');
     return FALSE;
   }
@@ -853,180 +805,4 @@ function theme_token_list($tokens) {
   return theme('table', array('header' => $header, 'rows' => $rows));
 }
 
-/**
- * @section
- * Vocabulary Hooks.
- */
-
-/**
- * A hook for specifying information about the data store for vocabularies.
- *
- * The storage backend for controlled vocabularies has traditionally been
- * the Chado CV term tables. However, Tripal v3.0 introduces APIs for supporting
- * other backends.  Therefore, this function indicates to Tripal which
- * data stores are capable of providing support for terms.
- *
- * @return
- *   An array describing the storage backends implemented by the module. The
- *   keys are storage backend names. To avoid name clashes, storage
- *   backend names should be prefixed with the name of the module that
- *   exposes them. The values are arrays describing the storage backend,
- *   with the following key/value pairs:
- *
- *   label: The human-readable name of the storage backend.
- *   module:  The name of the module providing the support for this backend.
- *   description: A short description for the storage backend.
- *   settings: An array whose keys are the names of the settings available for
- *     the storage backend, and whose values are the default values for
- *     those settings.
- */
-function hook_vocab_storage_info() {
-  return array(
-    'term_chado_storage' => array(
-      'label' => t('Chado storage'),
-      'description' => t('Integrates terms stored in the local Chado database with Tripal entities.'),
-      'settings' => array(),
-    ),
-  );
-}
-
-
-/**
- * Creates a form for specifying a term for TripalEntity creation.
- *
- * This hook allows the module that implements a vocabulary storage backend
- * to provide the form necessary to select a term that will then be used for
- * creating a new TripalEntity type.  Tripal will expect that a 'vocabulary' and
- * 'accession' are in the $form_state['storage'] array. The 'vocabulary' and
- * must be the abbreviated uppercase vocabulary for the vocabulary (e.g. 'RO',
- * 'SO', 'PATO', etc.).  The 'accession' must be the unique term ID (or
- * accession) for the term in the vocabulary.
- *
- * @param $form
- * @param $form_state
- *
- * @return
- *   A form object.
- */
-function hook_vocab_select_term_form(&$form, &$form_state) {
-
-  return $form;
-}
-/**
- * Validates the hook_vocab_select_term_form().
- *
- * @param $name
- */
-function hook_vocab_select_term_form_validate($form, &$form_state) {
-
-}
-/**
- * Provides a form for importing vocabularies and their terms.
- *
- * Tripal allows for vocabularies to be stored separately from the biological
- * data. This hook allows the default term storage backend to provide an
- * approprite form for importing ontologies (either in OBO or OWL format).
- *
- * @param $form
- * @param $form_state
- *
- */
-function hook_vocab_import_form($form, &$form_state) {
-  return $form;
-}
-function hook_vocab_import_form_validate($form, &$form_state) {
-
-}
-function hook_vocab_import_form_submit($form, &$form_state) {
-
-}
-
-/**
- * Hook used by the default term storage backend to provide details for a term.
- *
- * This hook is called by the tripal_entity module to retrieve information
- * about the term from the storage backend.  It must return an array with
- * a set of keys.
- *
- * @param $vocabulary
- *   The vocabulary 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:
- *     -vocabulary : An associative array with the following keys
- *       -name:  The short name for the vocabulary (e.g. SO, PATO, etc).
- *       -description: The description of this vocabulary.
- *       -url: The URL for 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 hook_vocab_get_term($vocabulary, $accession) {
-  // See the tripal_chado_vocab_get_term() function for an example.
-
-}
-
-/**
- * Hook used by the default term storage backend to add new terms.
- *
- * @param $values
- *   An associative array of key/value pairs used to add a new term.  The
- *   keys are:
- *     vocabulary : The vocabulary 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.
- * @return
- *   TRUE if the term was added, FALSE otherwise.  If the term already exists
- *   it will be updated and the return value will be TRUE,
- */
-function hook_vocab_set_term($values) {
-  // See the tripal_chado_vocab_set_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 $vocabulary
- *   The vocabulary 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:
- *     vocabulary : The short name of the vocabulary (e.g. SO, PATO, foaf).
- *     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($vocabulary, $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($vocabulary, $accession);
-    }
-  }
-}
 

+ 70 - 11
tripal/api/tripal.fields.api.inc

@@ -1,5 +1,6 @@
 <?php
 
+
 /**
  * Executes a TripalFieldQuery using the provided conditions.
  *
@@ -33,16 +34,14 @@ function hook_field_storage_tquery($conditions, $orderBy) {
  * Retrieves a list of TripalField types.
  *
  * The TripalField classes can be added by a site developer and should be
- * placed in the [module]/includes/fields directory.  Tripal will support
+ * placed in the [module]/includes/TripalFields directory.  Tripal will support
  * any field as long as it is in this directory and extends the TripalField
  * class.  To support dynamic inclusion of new fields this function
  * will look for TripalField class files and return a type for
  * each one.
  *
- * @param $module
- *   The module that provides fields.
  * @return
- *   A list of TripalField field type.
+ *   A list of TripalField names.
  */
 function tripal_get_field_types() {
   $types = array();
@@ -56,30 +55,90 @@ function tripal_get_field_types() {
     foreach ($field_files as $file) {
       $field_type = $file->name;
       module_load_include('inc', $module, 'includes/TripalFields/' . $field_type);
-      if (class_exists($field_type)) {
+      if (class_exists($field_type) and is_subclass_of($field_type, 'TripalField')) {
         $types[] = $field_type;
       }
     }
   }
   return $types;
 }
+/**
+ * Retrieves a list of TripalFieldWidgets.
+ *
+ * The TripalFieldWidget classes can be added by a site developer and should be
+ * placed in the [module]/includes/TripalFields directory.  Tripal will support
+ * any widget as long as it is in this directory and extends the
+ * TripalFieldWidget class.
+ *
+ * @return
+ *   A list of TripalFieldWidget names.
+ */
+function tripal_get_field_widgets() {
+  $widgets = array();
+
+  $modules = module_list(TRUE);
+  foreach ($modules as $module) {
+    // Find all of the files in the tripal_chado/includes/fields directory.
+    $fields_path = drupal_get_path('module', $module) . '/includes/TripalFields';
+    $field_files = file_scan_directory($fields_path, '/.*\.inc$/');
+    // Iterate through the fields, include the file and run the info function.
+    foreach ($field_files as $file) {
+      $field_type = $file->name;
+      module_load_include('inc', $module, 'includes/TripalFields/' . $field_type);
+      if (class_exists($field_type) and is_subclass_of($field_type, 'TripalFieldWidget')) {
+        $widgets[] = $field_type;
+      }
+    }
+  }
+  return $widgets;
+}
+/**
+ * Retrieves a list of TripalFieldFormatters.
+ *
+ * The TripalFieldFormatter classes can be added by a site developer and should
+ * be placed in the [module]/includes/TripalFields directory.  Tripal will
+ * support any widget as long as it is in this directory and extends the
+ * TripalFieldFormatter class.
+ *
+ * @return
+ *   A list of TripalFieldFormatter names.
+ */
+function tripal_get_field_formatters() {
+  $formatters = array();
+
+  $modules = module_list(TRUE);
+  foreach ($modules as $module) {
+    // Find all of the files in the tripal_chado/includes/fields directory.
+    $fields_path = drupal_get_path('module', $module) . '/includes/TripalFields';
+    $field_files = file_scan_directory($fields_path, '/.*\.inc$/');
+    // Iterate through the fields, include the file and run the info function.
+    foreach ($field_files as $file) {
+      $field_type = $file->name;
+      module_load_include('inc', $module, 'includes/TripalFields/' . $field_type);
+      if (class_exists($field_type) and is_subclass_of($field_type, 'TripalFieldFormatter')) {
+        $formatters[] = $field_type;
+      }
+    }
+  }
+  return $formatters;
+}
 /**
  * Loads the TripalField class file into scope.
  *
- * @param $field_type
- *   The type of field to instantiate
+ * @param $class
+ *   The class to instantiate
  *
  * @return
  *   TRUE if the field type class file was found, FALSE otherwise.
  */
-function tripal_load_include_field_type($field_type) {
+function tripal_load_include_field_class($class) {
 
   $modules = module_list(TRUE);
   foreach ($modules as $module) {
-    $file_path = realpath(".") . '/' . drupal_get_path('module', $module) . '/includes/TripalFields/' . $field_type . '.inc';
+    $file_path = realpath(".") . '/' . drupal_get_path('module', $module) . '/includes/TripalFields/' . $class . '.inc';
     if (file_exists($file_path)) {
-      module_load_include('inc', $module, 'includes/TripalFields/' . $field_type);
-      if (class_exists($field_type)) {
+      module_load_include('inc', $module, 'includes/TripalFields/' . $class);
+      if (class_exists($class)) {
         return TRUE;
       }
     }

+ 215 - 0
tripal/api/tripal.terms.api.inc

@@ -0,0 +1,215 @@
+<?php
+/**
+ * @section
+ * Vocabulary Hooks.
+ */
+
+/**
+ * A hook for specifying information about the data store for vocabularies.
+ *
+ * The storage backend for controlled vocabularies has traditionally been
+ * the Chado CV term tables. However, Tripal v3.0 introduces APIs for supporting
+ * other backends.  Therefore, this function indicates to Tripal which
+ * data stores are capable of providing support for terms.
+ *
+ * @return
+ *   An array describing the storage backends implemented by the module. The
+ *   keys are storage backend names. To avoid name clashes, storage
+ *   backend names should be prefixed with the name of the module that
+ *   exposes them. The values are arrays describing the storage backend,
+ *   with the following key/value pairs:
+ *
+ *   label: The human-readable name of the storage backend.
+ *   module:  The name of the module providing the support for this backend.
+ *   description: A short description for the storage backend.
+ *   settings: An array whose keys are the names of the settings available for
+ *     the storage backend, and whose values are the default values for
+ *     those settings.
+ */
+function hook_vocab_storage_info() {
+  return array(
+    'term_chado_storage' => array(
+      'label' => t('Chado storage'),
+      'description' => t('Integrates terms stored in the local Chado database with Tripal entities.'),
+      'settings' => array(),
+    ),
+  );
+}
+
+
+/**
+ * Creates a form for specifying a term for TripalEntity creation.
+ *
+ * This hook allows the module that implements a vocabulary storage backend
+ * to provide the form necessary to select a term that will then be used for
+ * creating a new TripalEntity type.  Tripal will expect that a 'vocabulary' and
+ * 'accession' are in the $form_state['storage'] array. The 'vocabulary' and
+ * must be the abbreviated uppercase vocabulary for the vocabulary (e.g. 'RO',
+ * 'SO', 'PATO', etc.).  The 'accession' must be the unique term ID (or
+ * accession) for the term in the vocabulary.
+ *
+ * @param $form
+ * @param $form_state
+ *
+ * @return
+ *   A form object.
+ */
+function hook_vocab_select_term_form(&$form, &$form_state) {
+
+  return $form;
+}
+/**
+ * Validates the hook_vocab_select_term_form().
+ *
+ * @param $name
+ */
+function hook_vocab_select_term_form_validate($form, &$form_state) {
+
+}
+/**
+ * Provides a form for importing vocabularies and their terms.
+ *
+ * Tripal allows for vocabularies to be stored separately from the biological
+ * data. This hook allows the default term storage backend to provide an
+ * approprite form for importing ontologies (either in OBO or OWL format).
+ *
+ * @param $form
+ * @param $form_state
+ *
+ */
+function hook_vocab_import_form($form, &$form_state) {
+  return $form;
+}
+function hook_vocab_import_form_validate($form, &$form_state) {
+
+}
+function hook_vocab_import_form_submit($form, &$form_state) {
+
+}
+
+/**
+ * Hook used by the default term storage backend to provide details for a term.
+ *
+ * This hook is called by the tripal_entity module to retrieve information
+ * about the term from the storage backend.  It must return an array with
+ * a set of keys.
+ *
+ * @param $vocabulary
+ *   The vocabulary 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:
+ *     -vocabulary : An associative array with the following keys
+ *       -name:  The short name for the vocabulary (e.g. SO, PATO, etc).
+ *       -description: The description of this vocabulary.
+ *       -url: The URL for 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 hook_vocab_get_term($vocabulary, $accession) {
+  // See the tripal_chado_vocab_get_term() function for an example.
+
+}
+
+/**
+ * Hook used by the default term storage backend to add new terms.
+ *
+ * @param $details
+ *   An array with at least the following keys:
+ *     -vocabulary : An associative array with the following keys
+ *       -name:  The short name for the vocabulary (e.g. SO, PATO, etc).
+ *       -description: The description of this vocabulary.
+ *       -url: The URL for 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.
+ * @return
+ *   TRUE if the term was added, FALSE otherwise.  If the term already exists
+ *   it will be updated and the return value will be TRUE,
+ */
+function hook_vocab_add_term($details) {
+  // See the tripal_chado_vocab_set_term() function for an example.
+}
+
+
+
+/**
+ * Adds a term to the vocabulary storage backend.
+ *
+ * Use this function to add new terms dynamically to the vocabulary storage
+ * backend.  If the term already exists no new term is added.
+ *
+ * @param $details
+ *   An array with at least the following keys:
+ *     -vocabulary : An associative array with the following keys
+ *       -name:  The short name for the vocabulary (e.g. SO, PATO, etc).
+ *       -description: The description of this vocabulary.
+ *       -url: The URL for 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.
+ * @return
+ *   TRUE if the term was added, FALSE otherwise.  If the term already exists
+ *   it will be updated and the return value will be TRUE,
+ */
+function tripal_add_term($details) {
+  // 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_add_term';
+    if (function_exists($function)) {
+      return $function($details);
+    }
+  }
+}
+
+/**
+ * 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 $vocabulary
+ *   The vocabulary 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:
+ *     vocabulary : The short name of the vocabulary (e.g. SO, PATO, foaf).
+ *     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($vocabulary, $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($vocabulary, $accession);
+    }
+  }
+}

+ 12 - 1
tripal/includes/TripalBundleController.inc

@@ -26,7 +26,16 @@ class TripalBundleController extends EntityAPIControllerExportable {
       'is_new' => TRUE,
       'data' => '',
     );
-    return parent::create($values);
+    $bundle = parent::create($values);
+
+    // Allow modules to make additions to the entity when it's created.
+    $modules = module_implements('bundle_create');
+    foreach ($modules as $module) {
+      $function = $module . '_bundle_create';
+      $function($bundle);
+    }
+
+    return $bundle;
   }
 
   /**
@@ -63,6 +72,8 @@ class TripalBundleController extends EntityAPIControllerExportable {
           }
         }
 
+        // TODO: this Chado sepcific code needs to be moved out of here!
+
         // Remove the entries in the chado_entity and tripal_entity t
         $query = db_select('chado_entity', 'ce');
         $query->join('tripal_entity', 'te', 'te.id = ce.entity_id');

+ 1 - 3
tripal/includes/TripalEntityController.inc

@@ -435,7 +435,7 @@ class TripalEntityController extends EntityAPIController {
       $entities += $queried_entities;
     }
 
-    // Entitycache module support: Add entities to the entity cache if we are
+    // Entity cache module support: Add entities to the entity cache if we are
     // not loading a revision.
     if (!empty($this->entityInfo['entity cache']) && !empty($queried_entities) && !$revision_id) {
       EntityCacheControllerHelper::entityCacheSet($this, $queried_entities);
@@ -470,8 +470,6 @@ class TripalEntityController extends EntityAPIController {
    * slow down the loading of pages and web services.  Therefore, we only
    * want to attach fields that are needed.
    *
-   *
-   *
    * @param $queried_entities
    *   The list of queried
    * @param $revision_id

+ 101 - 380
tripal/includes/TripalField.inc

@@ -1,45 +1,8 @@
 <?php
 
-
-/**
- * A base for fields attached Tripal Entities.
- *
- * This class is intended to simplify development of fields for Tripal Entities.
- * The Drupal Field API can still be used if desired, but the hope for this
- * class it to put the necessary functions in one place so that other Tripal
- * developers do not need to suffer the pain of navigating and learning the
- * Drupal Field API.
- *
- * To create a new field that can be attached to a Tripal Entity follow these
- * steps:
- * # Create a new class that inherits from TripalField
- * # Copy the editable constant variables (default_desription, default_label,
- *   default_settings and default_storage) to your class and edit as needed.
- *   Be sure not to rename these variables and be sure to keep the 'static'
- *   qualifier on them.
- * # Copy the functions you want to override. You will not need to copy the
- *   constructor, the static info() functions, or the getters and setters. In
- *   short you'll typically only need to override the Settingsform funtions,
- *   their validators and submitters, the load() function, and the widgetForm
- *   with it's validator and submitter.
- * # In your custom module implement the function hook_create_tripalfields()
- *   This function will be called anytime a new TripalEntity is created. It
- *   allows your module to create the new fields.  See the documentation for
- *   this function for creating the fields.  A field is usually only ever
- *   created once and can be reused on multiple entities.  So, even though
- *   this function is called everytime a new TripalEntity is created the fields
- *   will only be created once.
- * # In your custom module implement the function
- *   hook_create_tripalfield_instance().  This function is called anytime a
- *   new TripalEntity is created. It allows you to specify which fields are
- *   attached to an entity.  See the documentation for this hook function for
- *   more information.
- *
- */
 class TripalField {
 
 
-
   // --------------------------------------------------------------------------
   //                     EDITABLE STATIC CONSTANTS
   //
@@ -48,27 +11,40 @@ class TripalField {
   // the field and it's default widget and formatter.
   // --------------------------------------------------------------------------
 
+  // The term that this field maps to.  The format for the term should be:
+  // [vocab]:[accession] where [vocab] is the short name of the vocabulary
+  // and [acession] is the unique accession number for the term.  This term
+  // must already exist in the vocabulary storage backend. This
+  // value should never be changed once fields exist for this type.
+  public static $term = 'schema:Thing';
+
   // The default lable for this field.
-  public static $default_label = 'Tripal Field.';
+  public static $label = 'Tripal Field';
 
   // The default description for this field.
-  public static $default_description = 'The generic base class for all
-       Tripal Fields. Replace this text as appropriate for the child implementation.';
+  public static $description = 'The generic base class for all Tripal fields. ' .
+    'Replace this text as appropriate for the child implementation.';
 
   // Provide a list of global settings. These can be accessed witihn the
   // globalSettingsForm.  When the globalSettingsForm is submitted then
   // Drupal will automatically change these settings for all fields.
-  public static $default_settings = array();
+  public static $settings = array();
 
   // Provide a list of instance specific settings. These can be access within
   // the instanceSettingsForm.  When the instanceSettingsForm is submitted
   // then Drupal with automatically change these settings for the instnace.
   // It is recommended to put settings at the instance level whenever possible.
-  public static $default_instance_settings  = array();
+  public static $instance_settings  = array();
 
   // Set this to the name of the storage backend that by default will support
   // this field.
-  public static $default_storage = 'tripal_no_storage';
+  public static $storage = 'tripal_no_storage';
+
+  // The default widget for this field.
+  public static $default_widget = '';
+
+  // The default formatter for this field.
+  public static $default_formatter = '';
 
   // --------------------------------------------------------------------------
   //              PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
@@ -99,6 +75,15 @@ class TripalField {
   public function __construct($field, $instance = NULL) {
     $this->field = $field;
     $this->instance = $instance;
+
+    $class = get_called_class();
+    // Make sure the term exist.
+    list($vocabulary, $accession) = preg_split('/:/', $class::$term);
+    $term = tripal_get_term_details($vocabulary, $accession);
+    if (!$term) {
+      //throw new Error(t('Cannot create TripalField of type "%term" as that
+      //    term does not exist.', array('%term' => $class::$term)));
+    }
   }
 
   // --------------------------------------------------------------------------
@@ -116,72 +101,23 @@ class TripalField {
    *   describing the field type. The keys are the same as for the
    *   hook_field_info() function.
    */
-  public static function globalInfo() {
-    $field_type = get_called_class();
+  public static function info() {
+    $class = get_called_class();
     return array(
-      'label' => $field_type::$default_label,
-      'description' => $field_type::$default_description,
-      'default_widget' => $field_type . '_widget',
-      'default_formatter' => $field_type . '_formatter',
-      'settings' => $field_type::$default_settings,
-      'instance_settings' => $field_type::$default_instance_settings,
+      'label' => $class::$label,
+      'description' => $class::$description,
+      'default_widget' => $class::$default_widget,
+      'default_formatter' => $class::$default_formatter,
+      'settings' => $class::$settings,
+      'instance_settings' => $class::$instance_settings,
       'storage' => array(
-        'type' => $field_type::$default_storage,
+        'type' => $class::$storage,
         'module' => 'tripal',
         'active' => TRUE
       ),
     );
   }
 
-  /**
-   * Provides information about the widgets provided by this field.
-   *
-   * This function corresponds to the hook_field_widget_info() function of
-   * the Drupal Field API.
-   *
-   * This is a static function as it provides default values for all of the
-   * widgets for this field type, and thus we don't need an instantiated
-   * object to provide this information.
-   *
-   * @return
-   *   An associative array with key/value pairs compatible with those from the
-   *   hook_field_widget_info() function of the Drupal Field API.
-   */
-  public static function widgetInfo() {
-    $field_type = get_called_class();
-    return array(
-      $field_type . '_widget' => array(
-        'label' => $field_type::$default_label,
-        'field types' => array($field_type)
-      ),
-    );
-  }
-
-  /**
-   * Provides information about the formatter for this field.
-   *
-   * This function corresponds to the hook_field_formatter_info() function of
-   * the Drupal Field API.
-   *
-   * This is a static function as it provides default values for all of the
-   * formatters for this field type, and thus we don't need an instantiated
-   * object to provide this information.
-   *
-   * @return
-   *   An associative array with key/value paris compatible with those from the
-   *   hook_field_formatter_info() function of the Drupal Field API.
-   *
-   */
-  public static function formatterInfo() {
-    $field_type = get_called_class();
-    return array(
-      $field_type . '_formatter' => array(
-        'label' => $field_type::$default_label,
-        'field types' => array($field_type),
-        'settings' => array(),
-      ),
-    );
-  }
 
   // --------------------------------------------------------------------------
   //                 GETTERS AND SETTERS -- DO NOT OVERRIDE
@@ -203,192 +139,15 @@ class TripalField {
   public function getInstance() {
     return $this->instance;
   }
-
-
   // --------------------------------------------------------------------------
-  //                 OVERRIDEABLE FUNCTIONS
+  //                            OVERRIDEABLE FUNCTIONS
   // --------------------------------------------------------------------------
 
-  /**
-   * Provides a summary of the formatter settings.
-   *
-   * This function corresponds to the hook_field_formatter_settings_summary()
-   * function of the Drupal Field API.
-   *
-   * On the 'Manage Display' page of the content type administration page,
-   * fields are allowed to provide a settings form.  This settings form can
-   * be used to allow the site admin to define how the field should be
-   * formatted.  The settings are then available for the formatter()
-   * function of this class.  This function provides a text-based description
-   * of the settings for the site developer to see.  It appears on the manage
-   * display page inline with the field.  A field must always return a
-   * value in this function if the settings form gear button is to appear.
-   *
-   * See the hook_field_formatter_settings_summary() function for more
-   * information.
-   *
-   * @param $field
-   * @param $instance
-   * @param $view_mode
-   *
-   * @return string
-   *   A string that provides a very brief summary of the field settings
-   *   to the user.
-   *
-   */
-  public function formatterSettingsSummary($view_mode) {
-
-  }
-
-  /**
-   * Provides the field's setting form.
-   *
-   * This function corresponds to the hook_field_formatter_settings_form()
-   * function of the Drupal Field API.
-   *
-   * The settings form appears on the 'Manage Display' page of the content
-   * type administration page. This function provides the form that will
-   * appear on that page.
-   *
-   * To add a validate function, please create a static function in the
-   * implementing class, and indicate that this function should be used
-   * in the form array that is returned by this function.
-   *
-   * This form will not be displayed if the formatter_settings_summary()
-   * function does not return anything.
-   *
-   * @param $field
-   * @param $instance
-   * @param $view_mode
-   * @param $form
-   * @param $form_state
-   *
-   * @return
-   *   A Drupal Form array containing the settings form for this field.
-   */
-  public function formatterSettingsForm($view_mode, $form, &$form_state) {
-
-  }
-
-  /**
-   *  Provides the display for a field
-   *
-   * This function corresponds to the hook_field_formatter_view()
-   * function of the Drupal Field API.
-   *
-   *  This function provides the display for a field when it is viewed on
-   *  the web page.  The content returned by the formatter should only include
-   *  what is present in the $items[$delta]['values] array. This way, the
-   *  contents that are displayed on the page, via webservices and downloaded
-   *  into a CSV file will always be identical.  The view need not show all
-   *  of the data in the 'values' array.
-   *
-   *  @param $element
-   *  @param $entity_type
-   *  @param $entity
-   *  @param $langcode
-   *  @param $items
-   *  @param $display
-   *
-   *  @return
-   *    An element array compatible with that returned by the
-   *    hook_field_formatter_view() function.
-   */
-  public function formatterView(&$element, $entity_type, $entity, $langcode, $items, $display) {
-
-    foreach($items as $delta => $item) {
-      $element[$delta] = array(
-        '#type' => 'markup',
-        '#markup' => $item['value'],
-      );
-    }
-  }
-
-  /**
-   * Provides the form for editing of this field.
-   *
-   * This function corresponds to the hook_field_widget_form()
-   * function of the Drupal Field API.
-   *
-   * This form is diplayed when the user creates a new entity or edits an
-   * existing entity.  If the field is attached to the entity then the form
-   * provided by this function will be displayed.
-   *
-   * At a minimum, the form must have a 'value' element.  For Tripal, the
-   * 'value' element of a field always corresponds to the value that is
-   * presented to the end-user either directly on the page (with formatting)
-   * or via web services, or some other mechanism.  However, the 'value' is
-   * sometimes not enough for a field.  For example, the Tripal Chado module
-   * maps fields to table columns and sometimes those columns are foreign keys
-   * therefore, the Tripal Chado modules does not just use the 'value' but adds
-   * additional elements to help link records via FKs.  But even in this case
-   * the 'value' element must always be present in the return form and in such
-   * cases it's value should be set equal to that added in the 'load' function.
-   *
-   * @param $widget
-   * @param $form
-   *   The form structure where widgets are being attached to. This might be a
-   *   full form structure, or a sub-element of a larger form.
-   * @param $form_state
-   *   An associative array containing the current state of the form.
-   * @param $langcode
-   *   The language associated with $items.
-   * @param $items
-   *   Array of default values for this field.
-   * @param $delta
-   *   The order of this item in the array of subelements (0, 1, 2, etc).
-   * @param $element
-   * A form element array containing basic properties for the widget:
-   *  - #entity_type: The name of the entity the field is attached to.
-   *  - #bundle: The name of the field bundle the field is contained in.
-   *  - #field_name: The name of the field.
-   *  - #language: The language the field is being edited in.
-   *  - #field_parents: The 'parents' space for the field in the form. Most
-   *    widgets can simply overlook this property. This identifies the location
-   *    where the field values are placed within $form_state['values'], and is
-   *    used to access processing information for the field through the
-   *    field_form_get_state() and field_form_set_state() functions.
-   *  - #columns: A list of field storage columns of the field.
-   *  - #title: The sanitized element label for the field instance, ready for
-   *    output.
-   *  - #description: The sanitized element description for the field instance,
-   *    ready for output.
-   *  - #required: A Boolean indicating whether the element value is required;
-   *    for required multiple value fields, only the first widget's values are
-   *    required.
-   *  - #delta: The order of this item in the array of subelements; see
-   *    $delta above
-   */
-  public function widgetForm(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
-
-    $widget['value'] = array(
-      '#type' => 'value',
-      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
-    );
-    $widget['#field'] = $this->field;
-    $widget['#instance'] = $this->instance;
-    $widget['#element_validate'] = array('tripal_field_widget_form_validate');
-  }
-
-  /**
-   * Performs validation of the widgetForm.
-   *
-   * Use this validate to ensure that form values are entered correctly.  Note
-   * this is different from the validate() function which ensures that the
-   * field data meets expectations.
-   *
-   * @param $form
-   * @param $form_state
-   */
-  public function widgetFormValidate($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
-
-  }
-
   /**
    *  Perform validation of the field regardless how it is updated.
    *
-   *  Any errors encountered should be indicatd by adding a value to the $errors
-   *  array according to the instructions below.
+   *  Any errors encountered should be indicated by adding a value to the
+   *  $errors array according to the instructions below.
    *
    *  @param $entity_type
    *    The type of $entity.
@@ -417,45 +176,6 @@ class TripalField {
   }
 
 
-  /**
-   * Performs extra commands when the entity form is submitted.
-   *
-   * Drupal typically does not provide a submit hook for fields.  The
-   * TripalField provides one to allow for behind-the-scenes actions to
-   * occur.   This function should never be used for updates, deletes or
-   * inserts for the Chado table associated with the field.  Rather, the
-   * storage backend should be allowed to handle inserts, updates deletes.
-   * However, it is permissible to perform inserts, updates or deletions within
-   * Chado using this function.  Those operations can be performed if needed but
-   * on other tables not directly associated with the field.
-   *
-   * An example is the chado.feature_synonym table.  The chado_linker__synonym
-   * field allows the user to provide a brand new synonynm and it must add it
-   * to the chado.synonym table prior to the record in the
-   * chado.feature_synonym table.  This insert occurs in the widgetFormSubmit
-   * function.
-   *
-   *  @param $entity_type
-   *    The type of $entity.
-   *  @param $entity
-   *    The entity for the operation.
-   *  @param $field
-   *    The field structure for the operation.
-   *  @param $instance
-   *    The instance structure for $field on $entity's bundle.
-   *  @param $langcode
-   *    The language associated with $items.
-   *  @param $items
-   *    $entity->{$field['field_name']}[$langcode], or an empty array if unset.
-   *  @param $form
-   *    The submitted form array.
-   *  @param $form_state.
-   *    The form state array.
-   */
-  public function widgetFormSubmit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
-
-  }
-
   /**
    * Loads the field values from the underlying data store.
    *
@@ -488,64 +208,6 @@ class TripalField {
 
   }
 
-  /**
-   * Provides a form for the 'Field Settings' of an instance of this field.
-   *
-   * This function corresponds to the hook_field_instance_settings_form()
-   * function of the Drupal Field API.
-   *
-   * Validation of the instance settings form is not supported by Drupal, but
-   * the TripalField class does provide a mechanism for supporting validation.
-   * To allow for validation of your setting form you must call the parent
-   * in your child class:
-   *
-   * @code
-   *   $element = parent::instanceSettingsForm();
-   * @endcode
-   *
-   * Please note, the form generated with this function does not easily
-   * support AJAX calls in the same way that other Drupal forms do.  If you
-   * need to use AJAX you must manually alter the $form in your ajax call.
-   * The typical way to handle updating the form via an AJAX call is to make
-   * the changes in the form function itself but that doesn't work here.
-   */
-  public function instanceSettingsForm() {
-    $settings = $this->instance['settings'];
-    $element = array();
-
-    //     $element['semantic_web'] = array(
-    //       '#type' => 'textfield',
-    //       '#title' => 'Semantic Web',
-    //       '#description' => t('Each field must be associated with a term
-    //           from a controlled vocabulary.  This allows computer programs to understand
-    //           the data provided on this site.  Please be cautions changing these
-    //           values.  Defaults are set by Tripal and sites that use the same
-    //           terms can exchange information.'),
-    //       '#collapsed' => TRUE,
-    //       '#collapsible' => TRUE,
-    //       '#tree' => TRUE,
-    //     );
-    $element['#field'] = $this->field;
-    $element['#instance'] = $this->instance;
-    $element['#element_validate'][] = 'tripal_field_instance_settings_form_validate';
-
-    return $element;
-  }
-  /**
-   * Provides validation of the instance settings form.
-   *
-   * There is no equivalent function in the Drupal Field API. Validation
-   * of instance settings forms in Drupal is not supported. However, the
-   * TripalField provides this function to fill the gap.  See the
-   * documentation for the instanceSettingsForm() function for instructions
-   * to support use of this function.
-   *
-   * @param $form
-   * @param $form_state
-   */
-  public function instanceSettingsFormValidate($form, &$form_state) {
-
-  }
 
   /**
    * Provides a form for the 'Field Settings' of the field management page.
@@ -560,7 +222,7 @@ class TripalField {
    * @param $has_data
    *   TRUE if the field already has data, FALSE if not.
    */
-  public function globalSettingsForm($has_data) {
+  public function settingsForm($has_data) {
     $settings = $this->field['settings'];
     $element = array();
 
@@ -587,7 +249,7 @@ class TripalField {
    * @param unknown $form
    * @param unknown $form_state
    */
-  public function globalSettingsFormValidate($form, &$form_state) {
+  public function settingsFormValidate($form, &$form_state) {
 
   }
 
@@ -605,4 +267,63 @@ class TripalField {
 
   }
 
+  /**
+   * Provides a form for the 'Field Settings' of an instance of this field.
+   *
+   * This function corresponds to the hook_field_instance_settings_form()
+   * function of the Drupal Field API.
+   *
+   * Validation of the instance settings form is not supported by Drupal, but
+   * the TripalField class does provide a mechanism for supporting validation.
+   * To allow for validation of your setting form you must call the parent
+   * in your child class:
+   *
+   * @code
+   *   $element = parent::instanceSettingsForm();
+   * @endcode
+   *
+   * Please note, the form generated with this function does not easily
+   * support AJAX calls in the same way that other Drupal forms do.  If you
+   * need to use AJAX you must manually alter the $form in your ajax call.
+   * The typical way to handle updating the form via an AJAX call is to make
+   * the changes in the form function itself but that doesn't work here.
+   */
+  public function instanceSettingsForm() {
+    $settings = $this->instance['settings'];
+    $element = array();
+
+    //     $element['semantic_web'] = array(
+    //       '#type' => 'textfield',
+    //       '#title' => 'Semantic Web',
+    //       '#description' => t('Each field must be associated with a term
+    //           from a controlled vocabulary.  This allows computer programs to understand
+    //           the data provided on this site.  Please be cautions changing these
+    //           values.  Defaults are set by Tripal and sites that use the same
+    //           terms can exchange information.'),
+    //       '#collapsed' => TRUE,
+    //       '#collapsible' => TRUE,
+    //       '#tree' => TRUE,
+    //     );
+    $element['#field'] = $this->field;
+    $element['#instance'] = $this->instance;
+    $element['#element_validate'][] = 'tripal_field_instance_settings_form_validate';
+
+    return $element;
+  }
+  /**
+  * Provides validation of the instance settings form.
+  *
+  * There is no equivalent function in the Drupal Field API. Validation
+  * of instance settings forms in Drupal is not supported. However, the
+  * TripalField provides this function to fill the gap.  See the
+  * documentation for the instanceSettingsForm() function for instructions
+  * to support use of this function.
+  *
+  * @param $form
+  * @param $form_state
+  */
+  public function instanceSettingsFormValidate($form, &$form_state) {
+
+  }
+
 }

+ 148 - 0
tripal/includes/TripalFieldFormatter.inc

@@ -0,0 +1,148 @@
+<?php
+
+class TripalFieldFormatter {
+  // The default lable for this field.
+  public static $label = 'Tripal Field.';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array();
+
+  // The list of default settings for this formatter.
+  public static $settings = array();
+
+  /**
+   * Instantiates a new TripalFieldFormatter object.
+   *
+   * @param $field
+   *   An array containing the field data as returned by field_info_field()
+   * @param $instance
+   *   (Optional). Set the instance of this field when one is available. This
+   *   is necessary when working with instance specific functions such as the
+   *   formatterSettingsForm, widgetForm, etc.
+   */
+  public function __construct($field, $instance = NULL) {
+    $this->field = $field;
+    $this->instance = $instance;
+  }
+
+  /**
+   * Provides information about the formatter for this field.
+   *
+   * This function corresponds to the hook_field_formatter_info() function of
+   * the Drupal Field API.
+   *
+   * This is a static function as it provides default values for all of the
+   * formatters for this field type, and thus we don't need an instantiated
+   * object to provide this information.
+   *
+   * @return
+   *   An associative array with key/value paris compatible with those from the
+   *   hook_field_formatter_info() function of the Drupal Field API.
+   *
+   */
+  public static function info() {
+    $class = get_called_class();
+    return array(
+      'label' => $class::$label,
+      'field types' => $class::$field_types,
+      'settings' => $class::$settings,
+    );
+  }
+
+  /**
+   * Provides the field's setting form.
+   *
+   * This function corresponds to the hook_field_formatter_settings_form()
+   * function of the Drupal Field API.
+   *
+   * The settings form appears on the 'Manage Display' page of the content
+   * type administration page. This function provides the form that will
+   * appear on that page.
+   *
+   * To add a validate function, please create a static function in the
+   * implementing class, and indicate that this function should be used
+   * in the form array that is returned by this function.
+   *
+   * This form will not be displayed if the formatter_settings_summary()
+   * function does not return anything.
+   *
+   * @param $field
+   * @param $instance
+   * @param $view_mode
+   * @param $form
+   * @param $form_state
+   *
+   * @return
+   *   A Drupal Form array containing the settings form for this field.
+   */
+  public function settingsForm($view_mode, $form, &$form_state) {
+
+  }
+
+  /**
+   *  Provides the display for a field
+   *
+   * This function corresponds to the hook_field_formatter_view()
+   * function of the Drupal Field API.
+   *
+   *  This function provides the display for a field when it is viewed on
+   *  the web page.  The content returned by the formatter should only include
+   *  what is present in the $items[$delta]['values] array. This way, the
+   *  contents that are displayed on the page, via webservices and downloaded
+   *  into a CSV file will always be identical.  The view need not show all
+   *  of the data in the 'values' array.
+   *
+   *  @param $element
+   *  @param $entity_type
+   *  @param $entity
+   *  @param $langcode
+   *  @param $items
+   *  @param $display
+   *
+   *  @return
+   *    An element array compatible with that returned by the
+   *    hook_field_formatter_view() function.
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+
+    foreach($items as $delta => $item) {
+      $element[$delta] = array(
+        '#type' => 'markup',
+        '#markup' => $item['value'],
+      );
+    }
+  }
+
+  /**
+   * Provides a summary of the formatter settings.
+   *
+   * This function corresponds to the hook_field_formatter_settings_summary()
+   * function of the Drupal Field API.
+   *
+   * On the 'Manage Display' page of the content type administration page,
+   * fields are allowed to provide a settings form.  This settings form can
+   * be used to allow the site admin to define how the field should be
+   * formatted.  The settings are then available for the formatter()
+   * function of this class.  This function provides a text-based description
+   * of the settings for the site developer to see.  It appears on the manage
+   * display page inline with the field.  A field must always return a
+   * value in this function if the settings form gear button is to appear.
+   *
+   * See the hook_field_formatter_settings_summary() function for more
+   * information.
+   *
+   * @param $field
+   * @param $instance
+   * @param $view_mode
+   *
+   * @return string
+   *   A string that provides a very brief summary of the field settings
+   *   to the user.
+   *
+   */
+  public function settingsSummary($view_mode) {
+
+  }
+
+
+}

+ 167 - 0
tripal/includes/TripalFieldWidget.inc

@@ -0,0 +1,167 @@
+<?php
+
+class TripalFieldWidget {
+  // The default lable for this field.
+  public static $label = 'Tripal Field.';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('no_widget');
+
+
+  /**
+   * Instantiates a new TripalFieldWidget object.
+   *
+   * @param $field
+   *   An array containing the field data as returned by field_info_field()
+   * @param $instance
+   *   (Optional). Set the instance of this field when one is available. This
+   *   is necessary when working with instance specific functions such as the
+   *   formatterSettingsForm, widgetForm, etc.
+   */
+  public function __construct($field, $instance = NULL) {
+    $this->field = $field;
+    $this->instance = $instance;
+  }
+
+  /**
+   * Provides information about the widgets provided by this field.
+   *
+   * This function corresponds to the hook_field_widget_info() function of
+   * the Drupal Field API.
+   *
+   * This is a static function as it provides default values for all of the
+   * widgets for this field type, and thus we don't need an instantiated
+   * object to provide this information.
+   *
+   * @return
+   *   An associative array with key/value pairs compatible with those from the
+   *   hook_field_widget_info() function of the Drupal Field API.
+   */
+  public static function info() {
+    $class = get_called_class();
+    return array(
+      'label' => $class::$label,
+      'field types' => $class::$field_types,
+    );
+  }
+
+  /**
+   * Provides the form for editing of this field.
+   *
+   * This function corresponds to the hook_field_widget_form()
+   * function of the Drupal Field API.
+   *
+   * This form is diplayed when the user creates a new entity or edits an
+   * existing entity.  If the field is attached to the entity then the form
+   * provided by this function will be displayed.
+   *
+   * At a minimum, the form must have a 'value' element.  For Tripal, the
+   * 'value' element of a field always corresponds to the value that is
+   * presented to the end-user either directly on the page (with formatting)
+   * or via web services, or some other mechanism.  However, the 'value' is
+   * sometimes not enough for a field.  For example, the Tripal Chado module
+   * maps fields to table columns and sometimes those columns are foreign keys
+   * therefore, the Tripal Chado modules does not just use the 'value' but adds
+   * additional elements to help link records via FKs.  But even in this case
+   * the 'value' element must always be present in the return form and in such
+   * cases it's value should be set equal to that added in the 'load' function.
+   *
+   * @param $widget
+   * @param $form
+   *   The form structure where widgets are being attached to. This might be a
+   *   full form structure, or a sub-element of a larger form.
+   * @param $form_state
+   *   An associative array containing the current state of the form.
+   * @param $langcode
+   *   The language associated with $items.
+   * @param $items
+   *   Array of default values for this field.
+   * @param $delta
+   *   The order of this item in the array of subelements (0, 1, 2, etc).
+   * @param $element
+   * A form element array containing basic properties for the widget:
+   *  - #entity_type: The name of the entity the field is attached to.
+   *  - #bundle: The name of the field bundle the field is contained in.
+   *  - #field_name: The name of the field.
+   *  - #language: The language the field is being edited in.
+   *  - #field_parents: The 'parents' space for the field in the form. Most
+   *    widgets can simply overlook this property. This identifies the location
+   *    where the field values are placed within $form_state['values'], and is
+   *    used to access processing information for the field through the
+   *    field_form_get_state() and field_form_set_state() functions.
+   *  - #columns: A list of field storage columns of the field.
+   *  - #title: The sanitized element label for the field instance, ready for
+   *    output.
+   *  - #description: The sanitized element description for the field instance,
+   *    ready for output.
+   *  - #required: A Boolean indicating whether the element value is required;
+   *    for required multiple value fields, only the first widget's values are
+   *    required.
+   *  - #delta: The order of this item in the array of subelements; see
+   *    $delta above
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+    $widget['#field'] = $this->field;
+    $widget['#instance'] = $this->instance;
+    $widget['#element_validate'] = array('tripal_field_widget_form_validate');
+  }
+
+  /**
+   * Performs validation of the widgetForm.
+   *
+   * Use this validate to ensure that form values are entered correctly.  Note
+   * this is different from the validate() function which ensures that the
+   * field data meets expectations.
+   *
+   * @param $form
+   * @param $form_state
+   */
+  public function validate($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+
+  }
+
+
+  /**
+   * Performs extra commands when the entity form is submitted.
+   *
+   * Drupal typically does not provide a submit hook for fields.  The
+   * TripalField provides one to allow for behind-the-scenes actions to
+   * occur.   This function should never be used for updates, deletes or
+   * inserts for the Chado table associated with the field.  Rather, the
+   * storage backend should be allowed to handle inserts, updates deletes.
+   * However, it is permissible to perform inserts, updates or deletions within
+   * Chado using this function.  Those operations can be performed if needed but
+   * on other tables not directly associated with the field.
+   *
+   * An example is the chado.feature_synonym table.  The chado_linker__synonym
+   * field allows the user to provide a brand new synonynm and it must add it
+   * to the chado.synonym table prior to the record in the
+   * chado.feature_synonym table.  This insert occurs in the widgetFormSubmit
+   * function.
+   *
+   *  @param $entity_type
+   *    The type of $entity.
+   *  @param $entity
+   *    The entity for the operation.
+   *  @param $field
+   *    The field structure for the operation.
+   *  @param $instance
+   *    The instance structure for $field on $entity's bundle.
+   *  @param $langcode
+   *    The language associated with $items.
+   *  @param $items
+   *    $entity->{$field['field_name']}[$langcode], or an empty array if unset.
+   *  @param $form
+   *    The submitted form array.
+   *  @param $form_state.
+   *    The form state array.
+   */
+  public function submit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+
+  }
+}

+ 79 - 0
tripal/includes/TripalFields/rdfs__type.inc

@@ -0,0 +1,79 @@
+<?php
+
+class rdfs__type extends TripalField {
+
+  // The term that this field maps to.  The format for the term should be:
+  // [vocab]:[accession] where [vocab] is the short name of the vocabulary
+  // and [acession] is the unique accession number for the term.  This
+  // value should never be changed once fields exist for this type.
+  public static $term = 'rdfs:type';
+
+  // The default lable for this field.
+  public static $label = 'Content Type';
+
+  // The default description for this field.
+  public static $description = 'The resource content type.';
+
+  // Provide a list of global settings. These can be accessed witihn the
+  // globalSettingsForm.  When the globalSettingsForm is submitted then
+  // Drupal will automatically change these settings for all fields.
+  public static $settings = array();
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  public static $instance_settings  = array();
+
+  // Set this to the name of the storage backend that by default will support
+  // this field.
+  public static $storage = 'tripal_no_storage';
+
+  // The default widget for this field.
+  public static $default_widget = 'rdfs__type_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'rdfs__type_formatter';
+
+  /**
+   * @see TripalField::load()
+   */
+  public function load($entity, $details = array()) {
+    $bundle = tripal_load_bundle_entity(array('name' => $entity->bundle));
+    $entity->{$this->field['field_name']}['und'][0]['value'] = $bundle->label;
+  }
+
+
+  /**
+   *  @see TripalField::settingsForm()
+   */
+  public function settingsForm($has_data) {
+    $settings = $this->field['settings'];
+    $element = array();
+
+//     $element['semantic_web'] = array(
+//       '#type' => 'textfield',
+//       '#title' => 'Semantic Web',
+//       '#description' => t('Each field must be associated with a term
+//           from a controlled vocabulary.  This allows computer programs to understand
+//           the data provided on this site.  Please be cautions changing these
+//           values.  Defaults are set by Tripal and sites that use the same
+//           terms can exchange information.'),
+//       '#collapsed' => TRUE,
+//       '#collapsible' => TRUE,
+//       '#tree' => TRUE,
+//     );
+    $element['#field'] = $this->field;
+    $element['#instance'] = $this->instance;
+    $element['#element_validate'][] = 'tripal_field_settings_form_validate';
+
+    return $element;
+  }
+  /**
+   *  @see TripalField::settingsFormValidate()
+   */
+  public function settingsFormValidate($form, &$form_state) {
+
+  }
+
+}

+ 24 - 0
tripal/includes/TripalFields/rdfs__type_formatter.inc

@@ -0,0 +1,24 @@
+<?php
+
+class rdfs__type_formatter extends TripalFieldFormatter {
+  // The default lable for this field.
+  public static $label = 'Content Type';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('rdfs__type');
+
+  // The list of default settings for this formatter.
+  public static $settings = array();
+
+  /**
+   * @see TripalFieldFormatter::view()
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+    foreach ($items as $delta => $item) {
+      $element[$delta] = array(
+        '#type' => 'markup',
+        '#markup' => $item['value'],
+      );
+    }
+  }
+}

+ 23 - 0
tripal/includes/TripalFields/rdfs__type_widget.inc

@@ -0,0 +1,23 @@
+<?php
+
+class rdfs__type_widget extends TripalFieldWidget {
+  // The default lable for this field.
+  public static $label = 'Content Type';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('rdfs__type');
+
+  /**
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items,
+      $delta, $element) {
+
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+  }
+}

+ 17 - 2
tripal/includes/TripalTerm.inc

@@ -45,9 +45,24 @@ class TripalTerm extends Entity {
     return array('path' => '/vocabulary/' . $vocab . '/term/' . $this->id);
   }
 
+  // Getters //
+  public function getName() {
+    return $this->name;
+  }
+  public function getAccession() {
+    return $this->name;
+  }
   public function getDefinition() {
-
-    return '';
+    return $this->definition;
+  }
+  public function getURL() {
+    return $this->url;
+  }
+  public function getVocab() {
+    return $this->vocab;
+  }
+  public function getID() {
+    return $this->id;
   }
 
 }

+ 3 - 3
tripal/includes/tripal.entity.inc

@@ -46,10 +46,10 @@ function tripal_entity_info() {
     'access callback' => 'tripal_entity_access',
 
     // FALSE disables caching. Caching functionality is handled by Drupal core.
-//    'static cache' => FALSE,
+    'static cache' => TRUE,
 
-    // Disable caching of fields
-//    'field cache' => FALSE,
+    // Caching of fields
+    'field cache' => TRUE,
 
     // This entity doesn't support bundles.
     'bundles' => array (),

+ 3 - 1
tripal/includes/tripal.field_storage.inc

@@ -51,8 +51,10 @@ function tripal_field_storage_load($entity_type, $entities, $age,
       // Allow the creating module to alter the value if desired.  The
       // module should do this if the field has any other form elements
       // that need populationg besides the value which was set above.
-      tripal_load_include_field_type($field_type);
+      tripal_load_include_field_class($field_type);
       if (class_exists($field_type)) {
+
+
         $tfield = new $field_type($field);
         $tfield->load($entity);
       }

+ 228 - 138
tripal/includes/tripal.fields.inc

@@ -14,106 +14,135 @@ function tripal_field_info() {
   $info = array();
   $field_types = tripal_get_field_types();
   foreach ($field_types as $field_type) {
-    $info[$field_type] = $field_type::globalInfo();
+    $info[$field_type] = $field_type::info();
   }
   return $info;
 }
 
+/**
+ * Implements hook_info_alter().
+ */
+function tripal_field_info_alter(&$info) {
+  // Make sure all fields have a 'tripal_term' setting so we can map
+  // all fields to a vocabulary term for the semantic web.
+  foreach ($info as $field_name => $details) {
+    if(array_key_exists('settings', $details)) {
+      if (!array_key_exists('tripal_term', $details['settings'])) {
+        $info[$field_name]['settings']['tripal_term'] = '';
+      }
+    }
+    else {
+      $info[$field_name]['settings']['tripal_term'] = '';
+    }
+  }
+}
+
 /**
  * Implements hook_field_widget_info();
  */
 function tripal_field_widget_info() {
   $info = array();
-
-  $field_types = tripal_get_field_types();
-  foreach ($field_types as $field_type) {
-    $info += $field_type::widgetInfo();
+  $widgets = tripal_get_field_widgets();
+  foreach ($widgets as $widget) {
+    $info[$widget] = $widget::info();
   }
   return $info;
 }
+/**
+ * Implements hook_field_widget_info_alter();
+ */
+function tripal_field_widget_info_alter(&$info) {
+
+}
 
 /**
  * Implements hook_field_formatter_info().
  */
 function tripal_field_formatter_info() {
   $info = array();
-
-  $field_types = tripal_get_field_types();
-  foreach ($field_types as $field_type) {
-    $info += $field_type::formatterInfo();
+  $formatters = tripal_get_field_formatters();
+  foreach ($formatters as $formatter) {
+    $info[$formatter] = $formatter::info();
   }
   return $info;
 }
 
 /**
- *
+ * Implements hook_field_formatter_info_alter();
  */
-function tripal_create_tripalfields($entity_type, $bundle) {
-  $field_name = 'content_type';
-  $info = array();
-  $info[$field_name] = array(
-    'field_name' => $field_name,
-    'type' => 'content_type',
-    'cardinality' => 1,
-    'locked' => FALSE,
-    'storage' => array(
-      'type' => 'tripal_no_storage'
-    ),
-    'settings' => array(
-      'semantic_web' => 'rdfs:type',
-    ),
-  );
-  return $info;
+function tripal_field_formatter_info_alter(&$info) {
+
 }
 
 /**
+ * Implements hook_bundle_create().
  *
- * @param unknown $entity_type
- * @param unknown $bundle
+ * This is a Triapl defined hook and is called in the TripalBundle::create()
+ * function to allow modules to perform tasks when a bundle is created.
  */
-function tripal_create_tripalfield_instance($entity_type, $bundle) {
-  $field_name = 'content_type';
-  $info = array();
-  $info[$field_name] = array(
-    'field_name' => $field_name,
-    'entity_type' => 'TripalEntity',
-    'bundle' => $bundle->name,
-    'label' => 'Resource Type',
-    'description' => '',
-    'required' => FALSE,
-    'settings' => array(
-      'auto_attach' => TRUE,
-    ),
-    'widget' => array(
-      'type' => 'tripal_content_type_widget',
+function tripal_bundle_create($bundle) {
+  $field_type = 'rdfs__type';
+  $field_name = $bundle->name . '_' . $field_type;
+
+  // Add the field, unless it already exists.
+  if (!field_info_field($field_name)) {
+    $field = field_create_field(array(
+      'field_name' => $field_name,
+      'type' => $field_type,
+      'cardinality' => 1,
+      'locked' => FALSE,
+      'storage' => array(
+        'type' => 'tripal_no_storage'
+      ),
       'settings' => array(
-        'display_label' => 1,
       ),
-    ),
-    'display' => array(
-      'default' => array(
-        'label' => 'inline',
-        'type' => 'tripal_content_type_formatter',
-        'settings' => array(),
+    ));
+  }
+
+
+  // Add an instance of the field to the bundle.
+  if (!field_info_instance($bundle->type, $field_name, $bundle->name)) {
+    $instance = field_create_instance(array(
+      'field_name' => $field_name,
+      'entity_type' => 'TripalEntity',
+      'bundle' => $bundle->name,
+      'label' => 'Resource Type',
+      'description' => 'The resource type',
+      'required' => FALSE,
+      'settings' => array(
+        'auto_attach' => TRUE,
       ),
-    ),
-  );
-  return $info;
+      'widget' => array(
+        'type' => 'rdfs__type_widget',
+        'settings' => array(
+          'display_label' => 1,
+        ),
+      ),
+      'display' => array(
+        'default' => array(
+          'label' => 'inline',
+          'type' => 'rdfs__type_formatter',
+          'settings' => array(),
+        ),
+      ),
+    ));
+  }
 }
+
 /**
  * Implements hook_field_formatter_view().
  */
 function tripal_field_formatter_view($entity_type, $entity, $field,
     $instance, $langcode, $items, $display) {
 
-  $element = array();
-  $field_type = $field['type'];
-  $is_loaded = tripal_load_include_field_type($field_type);
-  if ($is_loaded) {
-    $tfield = new $field_type($field, $instance);
-    $tfield->formatterView($element, $entity_type, $entity, $langcode, $items, $display);
-  }
-  return $element;
+   $element = array();
+   $formatter_class = $display['type'];
+   $is_loaded = tripal_load_include_field_class($formatter_class);
+   if ($is_loaded) {
+     $formatter = new $formatter_class($field, $instance);
+     $formatter->view($element, $entity_type, $entity, $langcode, $items, $display);
+   }
+   return $element;
 }
 
 /**
@@ -140,21 +169,41 @@ function tripal_field_no_delete() {
  * the table to let the user know where fields are storing their data.
  */
 function tripal_form_field_ui_field_overview_form_alter(&$form, &$form_state, $form_id) {
+  //dpm($form);
+
   // Add the 'Storage Location' to the table header.
+  $form['fields']['#header'][] = 'Term';
   $form['fields']['#header'][] = 'Supported By * ';
 
+  // TODO: remove widgets that aren't appropriate for this entity, if the
+  // type is 'tripal_key_value'.
+  // Why is this sort not working!!??
+  $options = $form['fields']['_add_new_field']['widget_type']['#options']['Tripal complex field'];
+  asort($options);
+  $form['fields']['_add_new_field']['widget_type']['#options']['Tripal complex field'] = $options;
+
   // Add the storage location as the final column for each field.
   $storage_info = module_invoke_all('field_storage_info');
   foreach (element_children($form['fields']) as $field_name) {
+
+
     $field = field_info_field($field_name);
     // For rows in the tables that aren't fields, just add an empty value
     // for the storage column.
     if (!$field) {
+      $form['fields'][$field_name][] = array(
+        '#markup' => '',
+      );
       $form['fields'][$field_name][] = array(
         '#markup' => '',
       );
       continue;
     }
+    $term = $field['settings']['tripal_term'] ? $field['settings']['tripal_term'] : 'N/A';
+    $form['fields'][$field_name][] = array(
+      '#markup' => $term,
+    );
+
     $storage_type = $field['storage']['type'];
     $storage_label = array_key_exists('label', $storage_info[$storage_type]) ? $storage_info[$storage_type]['label'] : '';
     if ($storage_type == 'field_sql_storage') {
@@ -181,65 +230,108 @@ function tripal_form_field_ui_field_overview_form_alter(&$form, &$form_state, $f
   );
 }
 
+/**
+ * Implements hook_module_implements_alter()
+ *
+ * We want our edits to the field_ui_field_overview_form form to occur after
+ * all modules have implemented their changes.
+ */
+function tripal_module_implements_alter(&$implementations, $hook) {
+  if ($hook == 'form_alter') {
+    $group = $implementations['tripal'];
+    unset($implementations['tripal']);
+    $implementations['tripal'] = $group;
+  }
+}
 
 
 /**
  * Implements hook_field_settings_form()
  */
 function tripal_field_settings_form($field, $instance, $has_data) {
-  $form = array();
-  $field_type = $field['type'];
-  //$is_loaded = tripal_load_include_field_type($field_type);
-  tripal_load_include_field_type($field_type);
-  if (class_exists($field_type)) {
-    $tfield = new $field_type($field, $instance);
-    $form = $tfield->globalSettingsForm($field, $instance, $has_data);
-  }
-  return $form;
+//   $form = array();
+//   $field_type = $field['type'];
+//   //$is_loaded = tripal_load_include_field_class($field_type);
+//   tripal_load_include_field_class($field_type);
+//   if (class_exists($field_type)) {
+//     $tfield = new $field_type($field, $instance);
+//     $form = $tfield->globalSettingsForm($field, $instance, $has_data);
+//   }
+//   return $form;
+}
+
+/**
+ * Allows for altering of a field's instance setting form.
+ *
+ * This appears to be a Drupal hook but is actually a custom function created
+ * by this module. It is called by the tripal_form_alter() function of this
+ * module.
+ *
+ * @param $form
+ *   The form array.  Alterations to the form can be made within this array.
+ * @param $form_state
+ *   The form state array.
+ */
+function tripal_field_instance_settings_form_alter(&$form, $form_state) {
+  $field = $form['#field'];
+  $instance = $form['#instance'];
+
+  $form['tripal_additions'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Tripal Settings',
+  );
+  $form['tripal_additions']['semantic_web'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Vocabulary Term'
+  );
+  $form['tripal_additions']['storage'] = array(
+    '#type' => 'textfield',
+    '#title' => 'Storage Backend'
+  );
 }
 /**
  * Implements hook_instance_settings_form()
  */
 function tripal_field_instance_settings_form($field, $instance) {
-  $form = array();
-  $field_type = $field['type'];
-  tripal_load_include_field_type($field_type);
-  if (class_exists($field_type)) {
-    $tfield = new $field_type($field, $instance);
-    $form = $tfield->instanceSettingsForm();
-  }
-  return $form;
+//   $form = array();
+//   $field_type = $field['type'];
+//   tripal_load_include_field_class($field_type);
+//   if (class_exists($field_type)) {
+//     $tfield = new $field_type($field, $instance);
+//     $form = $tfield->instanceSettingsForm();
+//   }
+//   return $form;
 }
 /**
  *
  */
 function tripal_field_instance_settings_form_validate($form, &$form_state) {
-  $field = $form['#field'];
-  $instance = $form['#instance'];
-  $field_type = $field['type'];
-  tripal_load_include_field_type($field_type);
-  if (class_exists($field_type)) {
-    $tfield = new $field_type($field, $instance);
-    $form = $tfield->instanceSettingsFormValidate($form, $form_state);
-  }
+//   $field = $form['#field'];
+//   $instance = $form['#instance'];
+//   $field_type = $field['type'];
+//   tripal_load_include_field_class($field_type);
+//   if (class_exists($field_type)) {
+//     $tfield = new $field_type($field, $instance);
+//     $form = $tfield->instanceSettingsFormValidate($form, $form_state);
+//   }
 }
 
 /**
  *
  */
 function tripal_field_widget_form_validate($form, &$form_state) {
-  $entity = $form['#entity'];
-  $entity_type = $form['#entity_type'];
-  $langcode = $form['#language'];
-  $delta = $form['#delta'];
-  $field = $form['#field'];
-  $field_type = $field['type'];
-  tripal_load_include_field_type($field_type);
-  if (class_exists($field_type)) {
-    $instance = $form['#instance'];
-    $tfield = new $field_type($field, $instance);
-    $form = $tfield->widgetFormValidate($form, $form_state, $entity_type, $entity, $langcode, $delta);
-  }
+//   $entity = $form['#entity'];
+//   $entity_type = $form['#entity_type'];
+//   $langcode = $form['#language'];
+//   $delta = $form['#delta'];
+//   $field = $form['#field'];
+//   $field_type = $field['type'];
+//   tripal_load_include_field_class($field_type);
+//   if (class_exists($field_type)) {
+//     $instance = $form['#instance'];
+//     $tfield = new $field_type($field, $instance);
+//     $form = $tfield->widgetFormValidate($form, $form_state, $entity_type, $entity, $langcode, $delta);
+//   }
 }
 
 
@@ -251,14 +343,14 @@ function tripal_field_widget_form_validate($form, &$form_state) {
  * member function.
  */
 function tripal_field_settings_form_validate($form, &$form_state) {
-  $field = $form['#field'];
-  $instance = $form['#instance'];
-  $field_type = $field['type'];
-  tripal_load_include_field_type($field_type);
-  if (class_exists($field_type)) {
-    $tfield = new $field_type($field, $instance);
-    $form = $tfield->globalSettingsFormValidate($field, $instance, $form, $form_state);
-  }
+//   $field = $form['#field'];
+//   $instance = $form['#instance'];
+//   $field_type = $field['type'];
+//   tripal_load_include_field_class($field_type);
+//   if (class_exists($field_type)) {
+//     $tfield = new $field_type($field, $instance);
+//     $form = $tfield->globalSettingsFormValidate($field, $instance, $form, $form_state);
+//   }
 }
 
 
@@ -267,14 +359,14 @@ function tripal_field_settings_form_validate($form, &$form_state) {
  */
 function tripal_field_formatter_settings_summary($field, $instance, $view_mode) {
 
-  $summary = '';
-  $field_type = $field['type'];
-  tripal_load_include_field_type($field_type);
-  if (class_exists($field_type)) {
-    $tfield = new $field_type($field, $instance);
-    $form = $tfield->formatterSettingsSummary($view_mode);
-  }
-  return $summary;
+//   $summary = '';
+//   $field_type = $field['type'];
+//   tripal_load_include_field_class($field_type);
+//   if (class_exists($field_type)) {
+//     $tfield = new $field_type($field, $instance);
+//     $form = $tfield->formatterSettingsSummary($view_mode);
+//   }
+//   return $summary;
 }
 
 /**
@@ -283,14 +375,14 @@ function tripal_field_formatter_settings_summary($field, $instance, $view_mode)
 function tripal_formatter_settings_form($field, $instance,
     $view_mode, $form, &$form_state) {
 
-  $form = array();
-  $field_type = $field['type'];
-  tripal_load_include_field_type($field_type);
-  if (class_exists($field_type)) {
-    $tfield = new $field_type($field, $instance);
-    $form = $tfield->formatterSettingsForm($view_mode, $form, $form_state);
-  }
-  return $form;
+//   $form = array();
+//   $field_type = $field['type'];
+//   tripal_load_include_field_class($field_type);
+//   if (class_exists($field_type)) {
+//     $tfield = new $field_type($field, $instance);
+//     $form = $tfield->formatterSettingsForm($view_mode, $form, $form_state);
+//   }
+//   return $form;
 }
 
 
@@ -299,16 +391,14 @@ function tripal_formatter_settings_form($field, $instance,
  */
 function tripal_field_widget_form(&$form, &$form_state, $field,
     $instance, $langcode, $items, $delta, $element) {
-  $widget = $element;
-  $field_type = $field['type'];
-  tripal_load_include_field_type($field_type);
-  if (class_exists($field_type)) {
-    $tfield = new $field_type($field, $instance);
-    $tfield->widgetForm($widget, $form, $form_state, $langcode, $items, $delta, $element);
-  }
-  return $widget;
-
 
+   $widget_class = $instance['widget']['type'];
+   tripal_load_include_field_class($widget_class);
+   if (class_exists($widget_class)) {
+     $widget = new $widget_class($field, $instance);
+     $widget->form($element, $form, $form_state, $langcode, $items, $delta, $element);
+   }
+   return $element;
 }
 
 
@@ -353,13 +443,13 @@ function tripal_field_widget_form_alter(&$element, &$form_state, $context) {
 function tripal_field_validate($entity_type, $entity, $field, $instance,
     $langcode, $items, &$errors) {
 
-  $field_type = $field['type'];
-  $is_loaded = tripal_load_include_field_type($field_type);
-  if ($is_loaded) {
-    $tfield = new $field_type($field, $instance);
-    $tfield->validate($entity_type, $entity, $langcode,
-        $items, $errors);
-  }
+//   $field_type = $field['type'];
+//   $is_loaded = tripal_load_include_field_class($field_type);
+//   if ($is_loaded) {
+//     $tfield = new $field_type($field, $instance);
+//     $tfield->validate($entity_type, $entity, $langcode,
+//         $items, $errors);
+//   }
 }
 
 /**

+ 2 - 0
tripal/tripal.install

@@ -378,6 +378,7 @@ function tripal_tripal_variables_schema() {
  * Schema Definitions.
  */
 
+
 /**
  * The base table for Biological Data Entities.
  *
@@ -638,6 +639,7 @@ function tripal_tripal_bundle_schema() {
   return $schema;
 }
 
+
 /**
  * Additional Tripal Bundle Information.
  *

+ 15 - 0
tripal/tripal.module

@@ -25,6 +25,8 @@ require_once "includes/TripalBundle.inc";
 require_once "includes/TripalBundleController.inc";
 require_once "includes/TripalBundleUIController.inc";
 require_once "includes/TripalField.inc";
+require_once "includes/TripalFieldWidget.inc";
+require_once "includes/TripalFieldFormatter.inc";
 require_once "includes/TripalFieldQuery.inc";
 
 /**
@@ -555,9 +557,22 @@ function tripal_menu_alter(&$items) {
 function tripal_import_api() {
   module_load_include('inc', 'tripal', 'api/tripal.d3js.api');
   module_load_include('inc', 'tripal', 'api/tripal.fields.api');
+  module_load_include('inc', 'tripal', 'api/tripal.terms.api');
   module_load_include('inc', 'tripal', 'api/tripal.entities.api');
   module_load_include('inc', 'tripal', 'api/tripal.files.api');
   module_load_include('inc', 'tripal', 'api/tripal.jobs.api');
   module_load_include('inc', 'tripal', 'api/tripal.notice.api');
   module_load_include('inc', 'tripal', 'api/tripal.variables.api');
 }
+
+/**
+ * Implements hook_form_alter().
+ */
+function tripal_form_alter(&$form, $form_state, $form_id) {
+  // If this i the field_ui_field_edit_form (i.e. the form that appears
+  // when editing a field that is attached to an entity). Then we want
+  // to add semantic web settings.
+  if ($form_id == 'field_ui_field_edit_form') {
+    tripal_field_instance_settings_form_alter($form, $form_state);
+  }
+}

+ 2 - 2
tripal_chado/includes/TripalFields/chado_base__dbxref_id.inc → tripal_chado/includes/TripalFields.old/chado_base__dbxref_id.inc

@@ -5,8 +5,8 @@ class chado_base__dbxref_id extends TripalField {
   public static $default_label = 'Accession';
 
   // The default description for this field.
-  public static $default_description = 'This field specifies the unique stable accession (ID) for
-        this record. It requires that this site have a database entry.';
+  public static $default_description = 'The unique stable accession (ID) for
+        this record on this site.';
 
   // Add any default settings elements.  If you override the globalSettingsForm()
   // or the instanceSettingsForm() functions then you need to be sure that

+ 1 - 2
tripal_chado/includes/TripalFields/chado_base__organism_id.inc → tripal_chado/includes/TripalFields.old/chado_base__organism_id.inc

@@ -120,7 +120,6 @@ class chado_base__organism_id extends TripalField {
     // Set some defaults for the empty record.
     $entity->{$field_name}['und'][0] = array(
       'value' => array(
-        'chado-' . $field_table . '__organism_id' => '',
         'label' => '',
         'genus' => '',
         'species' => '',
@@ -168,7 +167,7 @@ class chado_base__organism_id extends TripalField {
   }
 
   /**
-   * @see TripalField::settings_form()
+   * @see TripalField::globalSettingsForm()
    */
   public function globalSettingsForm($has_data) {
     $element = parent::globalSettingsForm($has_data);

+ 0 - 0
tripal_chado/includes/TripalFields/chado_feature__md5checksum.inc → tripal_chado/includes/TripalFields.old/chado_feature__md5checksum.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_feature__residues.inc → tripal_chado/includes/TripalFields.old/chado_feature__residues.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_feature__seqlen.inc → tripal_chado/includes/TripalFields.old/chado_feature__seqlen.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_gene__transcripts.inc → tripal_chado/includes/TripalFields.old/chado_gene__transcripts.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__contact.inc → tripal_chado/includes/TripalFields.old/chado_linker__contact.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__cvterm.inc → tripal_chado/includes/TripalFields.old/chado_linker__cvterm.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__cvterm_adder.inc → tripal_chado/includes/TripalFields.old/chado_linker__cvterm_adder.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__dbxref.inc → tripal_chado/includes/TripalFields.old/chado_linker__dbxref.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__expression.inc → tripal_chado/includes/TripalFields.old/chado_linker__expression.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__featureloc.inc → tripal_chado/includes/TripalFields.old/chado_linker__featureloc.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__featurepos.inc → tripal_chado/includes/TripalFields.old/chado_linker__featurepos.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__genotype.inc → tripal_chado/includes/TripalFields.old/chado_linker__genotype.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__phenotype.inc → tripal_chado/includes/TripalFields.old/chado_linker__phenotype.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__prop.inc → tripal_chado/includes/TripalFields.old/chado_linker__prop.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__prop_adder.inc → tripal_chado/includes/TripalFields.old/chado_linker__prop_adder.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__pub.inc → tripal_chado/includes/TripalFields.old/chado_linker__pub.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__relationship.inc → tripal_chado/includes/TripalFields.old/chado_linker__relationship.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_linker__synonym.inc → tripal_chado/includes/TripalFields.old/chado_linker__synonym.inc


+ 0 - 0
tripal_chado/includes/TripalFields/chado_organism__type_id.inc → tripal_chado/includes/TripalFields.old/chado_organism__type_id.inc


+ 149 - 0
tripal_chado/includes/TripalFields/data__accession.inc

@@ -0,0 +1,149 @@
+<?php
+
+class data__accession extends TripalField {
+
+
+  // --------------------------------------------------------------------------
+  //                     EDITABLE STATIC CONSTANTS
+  //
+  // The following constants SHOULD be set for each descendent class.  They are
+  // used by the static functions to provide information to Drupal about
+  // the field and it's default widget and formatter.
+  // --------------------------------------------------------------------------
+
+  // The term that this field maps to.  The format for the term should be:
+  // [vocab]:[accession] where [vocab] is the short name of the vocabulary
+  // and [acession] is the unique accession number for the term.  This term
+  // must already exist in the vocabulary storage backend. This
+  // value should never be changed once fields exist for this type.
+  public static $term = 'data:2091';
+
+  // The default lable for this field.
+  public static $label = 'Accession';
+
+  // The default description for this field.
+  public static $description = 'The unique stable accession (ID) for
+        this record on this site.';
+
+  // Provide a list of global settings. These can be accessed witihn the
+  // globalSettingsForm.  When the globalSettingsForm is submitted then
+  // Drupal will automatically change these settings for all fields.
+  public static $settings = array(
+    'chado_table' => '',
+    'chado_column' => '',
+    'base_table' => '',
+    'semantic_web' => '',
+  );
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  public static $instance_settings  = array();
+
+  // Set this to the name of the storage backend that by default will support
+  // this field.
+  public static $storage = 'field_chado_storage';
+
+  // The default widget for this field.
+  public static $default_widget = 'data__accession_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'data__accession_formatter';
+
+  /**
+   * @see TripalField::load()
+   */
+  public function load($entity, $details = array()) {
+
+    $record = $details['record'];
+
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+
+
+    // Set some defauls for the empty record
+    $entity->{$field_name}['und'][0] = array(
+      'value' => array(
+        'vocabulary' => '',
+        'accession' => '',
+        'URL' => '',
+      ),
+      'chado-' . $field_table . '__' . $field_column => '',
+      'db_id' => '',
+      'accession' => '',
+      'version' => '',
+      'description' => '',
+    );
+
+    // Get the primary dbxref record (if it's not NULL).  Because we have a
+    // dbxref_id passed in by the base record, we will only have one record.
+    if ($record->$field_column) {
+      $dbxref = $record->$field_column;
+      $value = $dbxref->db_id->name . ':' . $dbxref->accession;
+      $entity->{$field_name}['und'][0] = array(
+        'value' => array(
+          'vocabulary' => $dbxref->db_id->name,
+          'accession' => $dbxref->accession,
+          'URL' => tripal_get_dbxref_url($dbxref),
+        ),
+        'chado-' . $field_table . '__' . $field_column => $record->$field_column->$field_column,
+        'db_id'       => $dbxref->db_id->db_id,
+        'accession'   => $dbxref->accession,
+        'version'     => $dbxref->version,
+        'description' => $dbxref->description,
+      );
+    }
+  }
+
+  /**
+   * @see TripalField::validate()
+   */
+  public function validate($entity_type, $entity, $field, $items, &$errors) {
+
+    $field_name = $this->field['field_name'];
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+
+    // Get the field values.
+    foreach ($items as $delta => $values) {
+      $fk_val = $values['chado-' . $field_table . '__' . $field_column];
+      $db_id = $values['db_id'];
+      $accession = $values['accession'];
+      $version = $values['version'];
+      $description = $values['description'];
+
+      // Make sure that if a database ID is provided that an accession is also
+      // provided.  Here we use the form_set_error function rather than the
+      // form_error function because the form_error will add a red_highlight
+      // around all of the fields in the fieldset which is confusing as it's not
+      // clear to the user what field is required and which isn't. Therefore,
+      // we borrow the code from the 'form_error' function and append the field
+      // so that the proper field is highlighted on error.
+      if (!$db_id and $accession) {
+        $errors[$field_name][$delta]['und'][] = array(
+          'message' => t("A database and the accession must both be provided for the primary cross reference."),
+          'error' => 'chado_base__dbxref',
+        );
+      }
+      if ($db_id and !$accession) {
+        $errors[$field_name][$delta]['und'][] = array(
+          'message' => t("A database and the accession must both be provided for the primary cross reference."),
+          'error' => 'chado_base__dbxref',
+        );
+      }
+      if (!$db_id and !$accession and ($version or $description)) {
+        $errors[$field_name][$delta]['und'][] = array(
+          'message' => t("A database and the accession must both be provided for the primary cross reference."),
+          'error' => 'chado_base__dbxref',
+        );
+      }
+    }
+  }
+
+}

+ 28 - 0
tripal_chado/includes/TripalFields/data__accession_formatter.inc

@@ -0,0 +1,28 @@
+<?php
+
+class data__accession_formatter extends TripalFieldFormatter {
+  // The default lable for this field.
+  public static $label = 'Accession';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('data__accession');
+
+  // The list of default settings for this formatter.
+  public static $settings = array();
+
+  /**
+   * @see TripalFieldFormatter::view()
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+
+    foreach ($items as $delta => $item) {
+      if ($item['value']) {
+        $content = $item['value']['vocabulary'] . ':' . $item['value']['accession'];
+        $element[$delta] = array(
+          '#type' => 'markup',
+          '#markup' => $content,
+        );
+      }
+    }
+  }
+}

+ 227 - 0
tripal_chado/includes/TripalFields/data__accession_widget.inc

@@ -0,0 +1,227 @@
+<?php
+class data__accession_widget extends TripalFieldWidget {
+  // The default lable for this field.
+  public static $label = 'Accession';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('data__accession');
+
+  /**
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+
+    // Get the field defaults.
+    $fk_val = '';
+    $db_id = '';
+    $accession = '';
+    $version = '';
+    $description = '';
+
+    // If the field already has a value then it will come through the $items
+    // array.  This happens when editing an existing record.
+    if (count($items) > 0 and array_key_exists($delta, $items)) {
+      $fk_val = $items[$delta]['chado-' . $field_table . '__' . $field_column];
+      $db_id = $items[$delta]['db_id'];
+      $accession = $items[$delta]['accession'];
+      $version = $items[$delta]['version'];
+      $description = $items[$delta]['description'];
+    }
+
+    // Check $form_state['values'] to see if an AJAX call set the values.
+    if (array_key_exists('values', $form_state)) {
+      $fk_val = isset($form_state['values'][$field_name]['und'][$delta]['chado-' . $field_table . '__' . $field_column]) ? $form_state['values'][$field_name]['und'][$delta]['chado-' . $field_table . '__' . $field_column] : '';
+      $db_id = isset($form_state['values'][$field_name]['und'][$delta]['db_id']) ? $form_state['values'][$field_name]['und'][$delta]['db_id'] : '';
+      $accession = isset($form_state['values'][$field_name]['und'][$delta]['accession']) ? $form_state['values'][$field_name]['und'][$delta]['accession'] : '';
+      $version = isset($form_state['values'][$field_name]['und'][$delta]['version']) ? $form_state['values'][$field_name]['und'][$delta]['version'] : '';
+      $description = isset($form_state['values'][$field_name]['und'][$delta]['description']) ? $form_state['values'][$field_name]['und'][$delta]['description'] : '';
+    }
+
+    $schema = chado_get_schema('dbxref');
+    $options = tripal_get_db_select_options();
+
+    //$widget['#element_validate'] = array('chado_base__dbxref_id_widget_validate');
+    $widget['#theme'] = 'data__accession_widget';
+    $widget['#prefix'] =  "<span id='$field_name-dbxref--db-id'>";
+    $widget['#suffix'] =  "</span>";
+
+    // A temporary element used for theming the fieldset.
+    $widget['#theme_settings'] = array(
+      '#title' => $element['#title'],
+      '#description' =>  $element['#description'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#theme' => 'data__accession_widget',
+      //'#collapsible' => TRUE,
+      //'#collapsed' => $collapsed,
+    );
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+
+    $widget['chado-' . $field_table . '__' . $field_column] = array(
+      '#type' => 'value',
+      '#default_value' => $fk_val,
+    );
+
+    $widget['db_id'] = array(
+      '#type' => 'select',
+      '#title' => t('Database'),
+      '#options' => $options,
+      '#required' => $element['#required'],
+      '#default_value' => $db_id,
+      '#ajax' => array(
+        'callback' => "data__accession_widget_form_ajax_callback",
+        'wrapper' => "$field_name-dbxref--db-id",
+        'effect' => 'fade',
+        'method' => 'replace'
+      ),
+    );
+    $widget['accession'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Accession'),
+      '#default_value' => $accession,
+      '#required' => $element['#required'],
+      '#maxlength' => array_key_exists('length', $schema['fields']['accession']) ? $schema['fields']['accession']['length'] : 255,
+      '#size' => 15,
+      '#autocomplete_path' => 'admin/tripal/storage/chado/auto_name/dbxref/' . $db_id,
+      '#ajax' => array(
+        'callback' => "tripal_chado_dbxref_widget_form_ajax_callback",
+        'wrapper' => "$field_name-dbxref--db-id",
+        'effect' => 'fade',
+        'method' => 'replace'
+      ),
+      '#disabled' => $db_id ? FALSE : TRUE,
+    );
+    $widget['version'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Version'),
+      '#default_value' => $version,
+      '#maxlength' => array_key_exists('length', $schema['fields']['version']) ? $schema['fields']['version']['length'] : 255,
+      '#size' => 5,
+      '#disabled' => $db_id ? FALSE : TRUE,
+    );
+    $widget['description'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Description'),
+      '#default_value' => $description,
+      '#size' => 20,
+      '#disabled' => $db_id ? FALSE : TRUE,
+    );
+    $widget['links'] = array(
+      '#type' => 'item',
+      '#markup' => l('Add a new database', 'admin/tripal/legacy/tripal_db/add', array('attributes' => array('target' => '_blank')))
+    );
+  }
+
+  /**
+   * @see TripalFieldWidget::submit()
+   */
+  public function submit($form, &$form_state, $entity_type, $entity, $langcode, $delta) {
+    $field_name = $this->field['field_name'];
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+
+    $fk_val = isset($form_state['values'][$field_name][$langcode][$delta]['chado-' . $field_table . '__' . $field_column]) ? $form_state['values'][$field_name][$langcode][$delta]['chado-' . $field_table . '__' . $field_column] : '';
+    $db_id = isset($form_state['values'][$field_name][$langcode][$delta]['db_id']) ? $form_state['values'][$field_name][$langcode][$delta]['db_id'] : '';
+    $accession = isset($form_state['values'][$field_name][$langcode][$delta]['accession']) ? $form_state['values'][$field_name][$langcode][$delta]['accession'] : '';
+    $version = isset($form_state['values'][$field_name][$langcode][$delta]['version']) ? $form_state['values'][$field_name][$langcode][$delta]['version'] : '';
+
+    // If user did not select a database, we want to remove dbxref_id from the
+    // field.
+    if (!$db_id) {
+      $form_state['values'][$field_name][$langcode][$delta]['chado-' . $field_table . '__dbxref_id'] = '__NULL__';
+    }
+    // If the dbxref_id does not match the db_id + accession then the user
+    // has selected a new dbxref record and we need to update the hidden
+    // value accordingly.
+    if ($db_id and $accession) {
+      $dbxref = chado_generate_var('dbxref', array('db_id' => $db_id, 'accession' => $accession));
+      if ($dbxref and $dbxref->dbxref_id != $fk_val) {
+        $form_state['values'][$field_name][$langcode][$delta]['chado-' . $field_table . '__dbxref_id'] = $dbxref->dbxref_id;
+      }
+    }
+  }
+}
+
+/**
+ * An Ajax callback for the tripal_chado_admin_publish_form..
+ */
+function data__accession_widget_form_ajax_callback($form, $form_state) {
+  $field_name = $form_state['triggering_element']['#parents'][0];
+  $field = field_info_field($field_name);
+  $field_type = $field['type'];
+  $field_table = $field['settings']['chado_table'];
+  $field_column = $field['settings']['chado_column'];
+  $field_prefix = 'chado-' . $field_table . '__' . $field_column;
+
+  //   $db_id = tripal_chado_get_field_form_values($field_name, $form_state, 0, $field_prefix . '--db_id');
+  //   $accession = tripal_chado_get_field_form_values($field_name, $form_state, 0, $field_prefix . '--accession');
+  if ($db_id and $accession) {
+    $values = array(
+      'db_id' => $db_id,
+      'accession' => $accession,
+    );
+    $options = array('is_duplicate' => TRUE);
+    $has_duplicate = chado_select_record('dbxref', array('*'), $values, $options);
+    if (!$has_duplicate) {
+      drupal_set_message('The selected cross reference is new and will be added for future auto completions.', 'warning');
+    }
+  }
+
+  return $form[$field_name];
+}
+
+function theme_data__accession_widget($variables) {
+  $element = $variables['element'];
+  $field_name = $element['#field_name'];
+  $field = field_info_field($field_name);
+  $field_type = $field['type'];
+  $field_table = $field['settings']['chado_table'];
+  $field_column = $field['settings']['chado_column'];
+  $field_prefix = 'chado-' . $field_table . '__' . $field_column;
+
+  $layout = "
+      <div class=\"primary-dbxref-widget\">
+        <div class=\"primary-dbxref-widget-item\">" .
+        drupal_render($element['db_id']) . "
+        </div>
+        <div class=\"primary-dbxref-widget-item\">" .
+        drupal_render($element['accession']) . "
+        </div>
+        <div class=\"primary-dbxref-widget-item\">" .
+        drupal_render($element['version']) . "
+        </div>
+        <div class=\"primary-dbxref-widget-item\">" .
+        drupal_render($element['description']) . "
+        </div>
+        <div class=\"primary-dbxref-widget-links\">" . drupal_render($element['links']) . "</div>
+      </div>
+    ";
+
+  //   $classes = array();
+  //   $classes[] = 'collapsible';
+  //   $theme_settings = $element['#theme_settings'];
+  //   if ($theme_settings['#collapsed'] == FALSE) {
+  //     $classes[] = 'collapsed';
+  //   }
+  $fieldset = array(
+    '#title' => $element['#title'],
+    '#value' => '',
+    '#description' => $element['#description'],
+    '#children' => $layout,
+    //    '#attributes' => array('class' => $classes),
+  );
+
+  return theme('fieldset', array('element' => $fieldset));
+}

+ 194 - 0
tripal_chado/includes/TripalFields/obi__organism.inc

@@ -0,0 +1,194 @@
+<?php
+
+class obi__organism extends TripalField {
+
+  // The term that this field maps to.  The format for the term should be:
+  // [vocab]:[accession] where [vocab] is the short name of the vocabulary
+  // and [acession] is the unique accession number for the term.  This term
+  // must already exist in the vocabulary storage backend. This
+  // value should never be changed once fields exist for this type.
+  public static $term = 'OBI:organism';
+
+  // The default lable for this field.
+  public static $label = 'Organism';
+
+  // The default description for this field.
+  public static $description = 'The organism to which this resource is sssociated.';
+
+  // Add any default settings elements.  If you override the globalSettingsForm()
+  // or the instanceSettingsForm() functions then you need to be sure that
+  // any settings you want those functions to manage are listed in this
+  // array.
+  public static $settings = array(
+    'field_display_string' => '<i>[organism.genus] [organism.species]</i>',
+    'chado_table' => '',
+    'chado_column' => '',
+    'base_table' => '',
+    'semantic_web' => '',
+  );
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  public static $instance_settings  = array();
+  // Set this to the name of the storage backend that by default will support
+  // this field.
+  public static $storage = 'field_chado_storage';
+
+  // The default widget for this field.
+  public static $default_widget = 'OBI__organism_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'OBI__organism_formatter';
+
+
+  /**
+   * @see TripalField::validate()
+   */
+  public function validate($entity_type, $entity, $field, $items, &$errors) {
+
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+
+    // Get the field values.
+    foreach ($items as $delta => $values) {
+
+      // Get the field values.
+      $organism_id = $values['chado-' . $field_table . '__organism_id'];
+      if (!$organism_id or $organism_id == 0) {
+        $errors[$field_name]['und'][0][] = array(
+          'message' =>  t("Please specify an organism."),
+          'error' => 'chado_base__organism_id'
+        );
+      }
+    }
+  }
+
+  /**
+   * @see TripalField::load()
+   */
+  public function load($entity, $details = array()) {
+
+    $record = $details['record'];
+    $settings = $this->field['settings'];
+
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+
+    // Get the terms for each of the keys for the 'values' property.
+    $label_term = 'rdfs:label';
+    $genus_term = tripal_get_chado_semweb_term('organism', 'genus');
+    $species_term = tripal_get_chado_semweb_term('organism', 'species');
+    $infraspecific_name_term = tripal_get_chado_semweb_term('organism', 'infraspecific_name');
+    $infraspecific_type_term = tripal_get_chado_semweb_term('organism', 'type_id');
+
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = array(
+      'value' => array(
+        $label_term => '',
+        $genus_term => '',
+        $species_term => '',
+      ),
+    );
+
+    if ($record) {
+      $organism = $record->organism_id;
+      $string = $settings['field_display_string'];
+      $label = tripal_replace_chado_tokens($string, $organism);
+      $entity->{$field_name}['und'][0]['value'] = array(
+        $label_term => $label,
+        $genus_term => $organism->genus,
+        $species_term => $organism->species,
+      );
+      // The infraspecific fiels were introdcued in Chado v1.3.
+      if (property_exists($organism, 'infraspecific_name')) {
+        $entity->{$field_name}['und'][0]['value'][$infraspecific_type_term] = NULL;
+        $entity->{$field_name}['und'][0]['value'][$infraspecific_name_term] = $organism->infraspecific_name;
+        if ($organism->type_id) {
+          $entity->{$field_name}['und'][0]['value'][$infraspecific_type_term] =  $organism->type_id->name;
+        }
+      }
+      $entity->{$field_name}['und'][0]['chado-' . $field_table . '__organism_id'] = $organism->organism_id;
+
+      // Is there a published entity for this organism?
+      if (property_exists($entity->chado_record->$field_column, 'entity_id')) {
+        $fk_entity_id = $entity->chado_record->$field_column->entity_id;
+        $entity->{$field_name}['und'][0]['value']['entity'] = 'TripalEntity:' . $fk_entity_id;
+      }
+    }
+  }
+
+  /**
+   * @see TripalField::globalSettingsForm()
+   */
+  public function settingsForm($has_data) {
+    $element = parent::globalSettingsForm($has_data);
+
+    $settings = $this->field['settings'];
+
+    $element['instructions'] = array(
+      '#type' => 'item',
+      '#markup' => 'You may rewrite the way this field is presented to the end-user.
+        The Rewrite Value field allows you to use tokens to indicate how the
+        value should be displayed.  Tokens will be substituted with appriorate
+        data from the database.  See the Available tokens list for the
+        tokens you may use.'
+    );
+
+    $element['field_display_string'] = array(
+      '#type' => 'textfield',
+      '#title' => 'Rewrite Value',
+      '#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' => $settings['field_display_string'],
+    );
+
+    $element['tokens'] = array(
+      '#type' => 'fieldset',
+      '#collapsed' => TRUE,
+      '#collapsible' => TRUE,
+      '#title' => 'Available Tokens'
+    );
+    $headers = array('Token', 'Description');
+    $rows = array();
+
+    // Here we use the tripal_get_chado_tokens rather than the
+    // tripal_get_entity_tokens because we can't gurantee that all organisms
+    // have entities.
+    $tokens = tripal_get_chado_tokens('organism');
+    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',
+    );
+    $element['tokens']['list'] = array(
+      '#type' => 'item',
+      '#markup' => theme_table($table_vars),
+    );
+
+    // Add in the semantic web fields.
+    $parent_elements = parent::settings_form($field, $instance, $has_data);
+    $element = array_merge($element, $parent_elements);
+
+    return $element;
+  }
+
+}

+ 33 - 0
tripal_chado/includes/TripalFields/obi__organism_formatter.inc

@@ -0,0 +1,33 @@
+<?php
+
+class obi__organism_formatter extends TripalFieldFormatter {
+
+  // The default lable for this field.
+  public static $label = 'Tripal Field.';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('obi__organism');
+
+  // The list of default settings for this formatter.
+  public static $settings = array();
+
+  /**
+   * @see TripalFieldFormatter::view()
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+    if (count($items) > 0) {
+      $content = $items[0]['value']['rdfs:label'];
+      if (array_key_exists('entity', $items[0]['value'])) {
+        list($entity_type, $entity_id) = explode(':', $items[0]['value']['entity']);
+        $content = l(strip_tags($items[0]['value']['rdfs:label']), 'bio_data/' . $entity_id);
+      }
+
+      // The cardinality of this field is 1 so we don't have to
+      // iterate through the items array, as there will never be more than 1.
+      $element[0] = array(
+        '#type' => 'markup',
+        '#markup' => $content,
+      );
+    }
+  }
+}

+ 46 - 0
tripal_chado/includes/TripalFields/obi__organism_widget.inc

@@ -0,0 +1,46 @@
+<?php
+
+class obi__organism_widget extends TripalFieldWidget {
+
+  // The default lable for this field.
+  public static $label = 'Organism';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('obi__organism');
+
+
+  /**
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->field['settings']['chado_table'];
+    $field_column = $this->field['settings']['chado_column'];
+
+    $organism_id = 0;
+    if (count($items) > 0 and array_key_exists('chado-' . $field_table . '__organism_id', $items[0])) {
+      $organism_id = $items[0]['chado-' . $field_table . '__organism_id'];
+    }
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+    $options = tripal_get_organism_select_options(FALSE);
+    $widget['chado-' . $field_table . '__organism_id'] = array(
+      '#type' => 'select',
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#options' => $options,
+      '#default_value' => $organism_id,
+      '#required' => $element['#required'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#delta' => $delta,
+    );
+  }
+}

+ 7 - 18
tripal_chado/includes/tripal_chado.entity.inc

@@ -1,19 +1,5 @@
 <?php
 
-/**
- * Implements hook_chado_bundle_create().
- *
- * This is a Tripal hook. It allows any module to perform tasks after
- * a bundle has been created.
- *
- * @param $bundle
- *  The TripalBundle object.
- */
-
-function tripal_chado_bundle_create($bundle) {
-
-}
-
 
 /**
  * Implements hook_entity_create().
@@ -69,6 +55,7 @@ function tripal_chado_entity_postsave($entity, $type) {
  * Implements hook_entity_load().
  */
 function tripal_chado_entity_load($entities, $type) {
+
   if ($type == 'TripalEntity') {
     foreach ($entities as $entity) {
 
@@ -105,10 +92,12 @@ function tripal_chado_entity_load($entities, $type) {
           ->condition('ce.entity_id', $entity->id)
           ->execute()
           ->fetchObject();
-        $schema = chado_get_schema($chado_table);
-        $record = chado_generate_var($chado_table, array($schema['primary key'][0] => $chado_entity->record_id));
-        $entity->chado_record = $record;
-        $entity->chado_record_id = $chado_entity->record_id;
+        if ($chado_entity) {
+          $schema = chado_get_schema($chado_table);
+          $record = chado_generate_var($chado_table, array($schema['primary key'][0] => $chado_entity->record_id));
+          $entity->chado_record = $record;
+          $entity->chado_record_id = $chado_entity->record_id;
+        }
       }
     }
   }

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

@@ -303,8 +303,8 @@ function tripal_chado_field_storage_load($entity_type, $entities, $age,
         // Allow the creating module to alter the value if desired.  The
         // module should do this if the field has any other form elements
         // that need populationg besides the value which was set above.
-        tripal_load_include_field_type($field_type);
-        if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
+        tripal_load_include_field_class($field_type);
+        if (class_exists($field_type) and is_subclass_of($field_type, 'TripalField')) {
           $tfield = new $field_type($field);
           $tfield->load($entity, array('record' => $record));
         }
@@ -317,7 +317,7 @@ function tripal_chado_field_storage_load($entity_type, $entities, $age,
 
         // Set an empty value by default, and let the hook function update it.
         $entity->{$field_name}['und'][0]['value'] = '';
-        tripal_load_include_field_type($field_type);
+        tripal_load_include_field_class($field_type);
         if (class_exists($field_type) && method_exists($field_type, 'load')) {
           $tfield = new $field_type($field);
           $tfield->load($entity, array('record' => $record));

+ 108 - 56
tripal_chado/includes/tripal_chado.fields.inc

@@ -1,12 +1,34 @@
 <?php
 
+/**
+ * Implements hook_chado_bundle_create().
+ *
+ * This is a Tripal hook. It allows any module to perform tasks after
+ * a bundle has been created.
+ *
+ * @param $bundle
+ *  The TripalBundle object.
+ */
+
+function tripal_chado_bundle_create($bundle) {
+  $entity_type = $bundle->type;
+
+  // Create/Add the new fields for this bundle.
+  tripal_chado_bundle_create_fields($entity_type, $bundle);
+
+  // Create/Add the new field instances for this bundle.
+  tripal_chado_bundle_create_instances($entity_type, $bundle);
+}
+
+
+
 /**
  * Implements hook_field_create_info().
  *
  * This is a Tripal defined hook that supports integration with the
  * TripalEntity field.
  */
-function tripal_chado_create_tripalfields($entity_type, $bundle) {
+function tripal_chado_bundle_create_fields($entity_type, $bundle) {
 
   // Get the table this bundle is mapped to.
   $term = tripal_load_term_entity(array('term_id' => $bundle->term_id));
@@ -29,21 +51,36 @@ function tripal_chado_create_tripalfields($entity_type, $bundle) {
   $info = array();
 
   // Create the fields for each column in the table.
-  tripal_chado_create_tripalfields_base($info, $details, $entity_type, $bundle);
+  tripal_chado_bundle_create_fields_base($info, $details, $entity_type, $bundle);
 
   // Create custom fields.
-  tripal_chado_create_tripalfields_custom($info, $details, $entity_type, $bundle);
-
+  tripal_chado_bundle_create_fields_custom($info, $details, $entity_type, $bundle);
+dpm($info);
   // Create fields for linking tables.
-  tripal_chado_create_tripalfields_linker($info, $details, $entity_type, $bundle);
+  //tripal_chado_bundle_create_fields_linker($info, $details, $entity_type, $bundle);
+
+  foreach ($info as $field_name => $details) {
+    $field_type = $details['type'];
+
+    // If the field already exists then skip it.
+    $field = field_info_field($details['field_name']);
+    if ($field) {
+      continue;
+    }
 
-  return $info;
+    // Create the field.
+    $field = field_create_field($details);
+    if (!$field) {
+      tripal_set_message(t("Could not create new field: %field.",
+          array('%field' =>  $details['field_name'])), TRIPAL_ERROR);
+    }
+  }
 }
 /**
  *
  * @param unknown $details
  */
-function tripal_chado_create_tripalfields_base(&$info, $details, $entity_type, $bundle) {
+function tripal_chado_bundle_create_fields_base(&$info, $details, $entity_type, $bundle) {
 
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
@@ -173,7 +210,7 @@ function tripal_chado_create_tripalfields_base(&$info, $details, $entity_type, $
  *
  * @param unknown $details
  */
-function tripal_chado_create_tripalfields_custom(&$info, $details, $entity_type, $bundle) {
+function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type, $bundle) {
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
   $type_field = $details['chado_type_column'];
@@ -181,10 +218,11 @@ function tripal_chado_create_tripalfields_custom(&$info, $details, $entity_type,
   $cvterm_id  = $details['chado_cvterm_id'];
   $schema = chado_get_schema($table_name);
 
-  // BASE DBXREF
-  if (array_key_exists('dbxref_id', $schema['fields'])) {
-    $field_name = $table_name . '__dbxref_id';
-    $field_type = 'chado_base__dbxref_id';
+
+  // BASE ORGANISM_ID
+  if ($table_name != 'organism' and array_key_exists('organism_id', $schema['fields'])) {
+    $field_name = $bundle->name . '_obi__organism';
+    $field_type = 'obi__organism';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'type' => $field_type,
@@ -195,16 +233,15 @@ function tripal_chado_create_tripalfields_custom(&$info, $details, $entity_type,
       ),
       'settings' => array(
         'chado_table' => $table_name,
-        'chado_column' => 'dbxref_id',
-        'semantic_web' => tripal_get_chado_semweb_term($table_name, 'dbxref_id'),
+        'chado_column' => 'organism_id',
       ),
     );
   }
 
-  // BASE ORGANISM_ID
-  if ($table_name != 'organism' and array_key_exists('organism_id', $schema['fields'])) {
-    $field_name = $table_name . '__organism_id';
-    $field_type = 'chado_base__organism_id';
+  // BASE DBXREF
+  if (array_key_exists('dbxref_id', $schema['fields'])) {
+    $field_name = $bundle->name . '_data__accession';
+    $field_type = 'data__accession';
     $info[$field_name] = array(
       'field_name' => $field_name,
       'type' => $field_type,
@@ -215,11 +252,13 @@ function tripal_chado_create_tripalfields_custom(&$info, $details, $entity_type,
       ),
       'settings' => array(
         'chado_table' => $table_name,
-        'chado_column' => 'organism_id',
-        'semantic_web' => tripal_get_chado_semweb_term($table_name, 'organism_id'),
+        'chado_column' => 'dbxref_id',
+        'semantic_web' => tripal_get_chado_semweb_term($table_name, 'dbxref_id'),
       ),
     );
   }
+  return;
+
 
   // FEATURE MD5CHECKSUM
   if ($table_name == 'feature') {
@@ -328,7 +367,7 @@ function tripal_chado_create_tripalfields_custom(&$info, $details, $entity_type,
  *
  * @param unknown $details
  */
-function tripal_chado_create_tripalfields_linker(&$info, $details, $entity_type, $bundle) {
+function tripal_chado_bundle_create_fields_linker(&$info, $details, $entity_type, $bundle) {
 
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
@@ -448,7 +487,7 @@ function tripal_chado_create_tripalfields_linker(&$info, $details, $entity_type,
       ),
     );
   }
-  
+
   // FEATUREPOS
   if ($table_name == 'feature') {
     $schema = chado_get_schema('featurepos');
@@ -618,7 +657,7 @@ function tripal_chado_create_tripalfields_linker(&$info, $details, $entity_type,
  * This is a Tripal defined hook that supports integration with the
  * TripalEntity field.
  */
-function tripal_chado_create_tripalfield_instance($entity_type, $bundle) {
+function tripal_chado_bundle_create_instances($entity_type, $bundle) {
 
   $term = tripal_load_term_entity(array('term_id' => $bundle->term_id));
   $vocab = $term->vocab;
@@ -637,11 +676,22 @@ function tripal_chado_create_tripalfield_instance($entity_type, $bundle) {
     'chado_type_column' => $mapped_table->chado_field,
   );
 
-  tripal_chado_create_tripalfield_instance_base($info, $entity_type, $bundle, $details);
-  tripal_chado_create_tripalfield_instance_custom($info, $entity_type, $bundle, $details);
-  tripal_chado_create_tripalfield_instance_linker($info, $entity_type, $bundle, $details);
+  tripal_chado_bundle_create_instances_base($info, $entity_type, $bundle, $details);
+  tripal_chado_bundle_create_instances_custom($info, $entity_type, $bundle, $details);
+  //tripal_chado_bundle_create_instances_linker($info, $entity_type, $bundle, $details);
+
+  foreach ($info as $field_name => $details) {
+    // If the field is already attached to this bundle then skip it.
+    $field = field_info_field($details['field_name']);
+    if ($field and array_key_exists('bundles', $field) and
+        array_key_exists('TripalEntity', $field['bundles']) and
+        in_array($bundle_name, $field['bundles']['TripalEntity'])) {
+      continue;
+    }
+    // Create the field instance.
+    $instance = field_create_instance($details);
+  }
 
-  return $info;
 }
 /**
  * Helper function for the hook_create_tripalfield_instance().
@@ -652,7 +702,7 @@ function tripal_chado_create_tripalfield_instance($entity_type, $bundle) {
  * @param $bundle
  * @param $details
  */
-function tripal_chado_create_tripalfield_instance_base(&$info, $entity_type, $bundle, $details) {
+function tripal_chado_bundle_create_instances_base(&$info, $entity_type, $bundle, $details) {
   $fields = array();
 
   // Get Chado information
@@ -828,7 +878,7 @@ function tripal_chado_create_tripalfield_instance_base(&$info, $entity_type, $bu
  * @param $bundle
  * @param $details
  */
-function tripal_chado_create_tripalfield_instance_custom(&$info, $entity_type, $bundle, $details) {
+function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bundle, $details) {
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
   $type_field = $details['chado_type_column'];
@@ -836,22 +886,26 @@ function tripal_chado_create_tripalfield_instance_custom(&$info, $entity_type, $
   $cvterm_id  = $details['chado_cvterm_id'];
   $schema = chado_get_schema($table_name);
 
-  // BASE DBXREF
-  if (array_key_exists('dbxref_id', $schema['fields'])) {
-    $field_name = $table_name . '__dbxref_id';
-    $info[$field_name] = array(
+  // BASE ORGANISM_ID
+  if ($table_name != 'organism' and array_key_exists('organism_id', $schema['fields'])) {
+    $field_name = $bundle->name . '_obi__organism';
+    $is_required = FALSE;
+    if (array_key_exists('not null', $schema['fields']['organism_id']) and
+        $schema['fields']['organism_id']['not null']) {
+      $is_required = TRUE;
+    }
+    $info[$field_name] =  array(
       'field_name' => $field_name,
       'entity_type' => $entity_type,
       'bundle' => $bundle->name,
-      'label' => 'Accession',
-      'description' => 'This field specifies the unique stable accession (ID) for
-        this record. It requires that this site have a database entry.',
-      'required' => FALSE,
+      'label' => 'Organism',
+      'description' => 'Select an organism.',
+      'required' => $is_required,
       'settings' => array(
         'auto_attach' => TRUE,
       ),
       'widget' => array(
-        'type' => 'chado_base__dbxref_id_widget',
+        'type' => 'obi__organism_widget',
         'settings' => array(
           'display_label' => 1,
         ),
@@ -859,33 +913,29 @@ function tripal_chado_create_tripalfield_instance_custom(&$info, $entity_type, $
       'display' => array(
         'default' => array(
           'label' => 'inline',
-          'type' => 'chado_base__dbxref_id_formatter',
+          'type' => 'obi__organism_formatter',
           'settings' => array(),
         ),
       ),
     );
   }
 
-  // BASE ORGANISM_ID
-  if ($table_name != 'organism' and array_key_exists('organism_id', $schema['fields'])) {
-    $field_name = $table_name . '__organism_id';
-    $is_required = FALSE;
-    if (array_key_exists('not null', $schema['fields']['organism_id']) and
-        $schema['fields']['organism_id']['not null']) {
-      $is_required = TRUE;
-    }
-    $info[$field_name] =  array(
+  // BASE DBXREF
+  if (array_key_exists('dbxref_id', $schema['fields'])) {
+    $field_name = $bundle->name . '_data__accession';
+    $info[$field_name] = array(
       'field_name' => $field_name,
       'entity_type' => $entity_type,
       'bundle' => $bundle->name,
-      'label' => 'Organism',
-      'description' => 'Select an organism.',
-      'required' => $is_required,
+      'label' => 'Accession',
+      'description' => 'This field specifies the unique stable accession (ID) for
+        this record. It requires that this site have a database entry.',
+      'required' => FALSE,
       'settings' => array(
         'auto_attach' => TRUE,
       ),
       'widget' => array(
-        'type' => 'chado_base__organism_id_widget',
+        'type' => 'chado_base__dbxref_id_widget',
         'settings' => array(
           'display_label' => 1,
         ),
@@ -893,12 +943,14 @@ function tripal_chado_create_tripalfield_instance_custom(&$info, $entity_type, $
       'display' => array(
         'default' => array(
           'label' => 'inline',
-          'type' => 'chado_base__organism_id_formatter',
+          'type' => 'chado_base__dbxref_id_formatter',
           'settings' => array(),
         ),
       ),
     );
   }
+  return;
+
 
   // FEATURE MD5CHECKSUM
   if ($table_name == 'feature') {
@@ -1061,7 +1113,7 @@ function tripal_chado_create_tripalfield_instance_custom(&$info, $entity_type, $
  * @param unknown $bundle
  * @param unknown $details
  */
-function tripal_chado_create_tripalfield_instance_linker(&$info, $entity_type, $bundle, $details) {
+function tripal_chado_bundle_create_instances_linker(&$info, $entity_type, $bundle, $details) {
 
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
@@ -1220,7 +1272,7 @@ function tripal_chado_create_tripalfield_instance_linker(&$info, $entity_type, $
       ),
     );
   }
-  
+
   // FEATUREPOS
   if ($table_name == 'feature') {
     $field_name = 'featurepos';
@@ -1249,7 +1301,7 @@ function tripal_chado_create_tripalfield_instance_linker(&$info, $entity_type, $
       ),
     );
   }
-  
+
   // GENOTYPE
   $genotype_table = $table_name . '_genotype';
   if (chado_table_exists($genotype_table)) {

+ 28 - 28
tripal_chado/includes/tripal_chado.setup.inc

@@ -123,7 +123,7 @@ function tripal_chado_prepare_chado() {
       'A vocabulary for storing synonym types.'
     );
     // set the default vocabularies
-    tripal_set_default_cv('synonym', 'type_id', 'synonym_type');
+    //tripal_set_default_cv('synonym', 'type_id', 'synonym_type');
 
     // Add cvterms.
     tripal_insert_misc_cvterms();
@@ -138,7 +138,7 @@ function tripal_chado_prepare_chado() {
     );
 
     // Set the default vocabularies.
-    tripal_set_default_cv('organismprop', 'type_id', 'organism_property');
+    //tripal_set_default_cv('organismprop', 'type_id', 'organism_property');
 
     // Add taxonomic terms.
     $obo_id = tripal_insert_obo('Taxonomic Rank', 'http://purl.obolibrary.org/obo/taxrank.obo');
@@ -160,7 +160,7 @@ function tripal_chado_prepare_chado() {
     tripal_analysis_add_mview_analysis_organism();
 
     // set the default vocabularies
-    tripal_set_default_cv('analysisprop', 'type_id', 'analysis_property');
+    //tripal_set_default_cv('analysisprop', 'type_id', 'analysis_property');
 
     /////////////////////////////////////////////////////////////////////////////
     //                        Chado Contact Module
@@ -190,9 +190,9 @@ function tripal_chado_prepare_chado() {
     tripal_contact_add_cvs();
 
     // Set the default vocabularies.
-    tripal_set_default_cv('contact', 'type_id', 'tripal_contact');
-    tripal_set_default_cv('contactprop', 'type_id', 'tripal_contact');
-    tripal_set_default_cv('contact_relationship', 'type_id', 'contact_relationship');
+    //('contact', 'type_id', 'tripal_contact');
+    //tripal_set_default_cv('contactprop', 'type_id', 'tripal_contact');
+    //tripal_set_default_cv('contact_relationship', 'type_id', 'contact_relationship');
 
     /////////////////////////////////////////////////////////////////////////////
     //                        Chado Feature Module
@@ -226,9 +226,9 @@ function tripal_chado_prepare_chado() {
     }
 
     // Set the default vocabularies.
-    tripal_set_default_cv('feature', 'type_id', 'sequence');
-    tripal_set_default_cv('featureprop', 'type_id', 'feature_property');
-    tripal_set_default_cv('feature_relationship', 'type_id', 'feature_relationship');
+    //tripal_set_default_cv('feature', 'type_id', 'sequence');
+    //tripal_set_default_cv('featureprop', 'type_id', 'feature_property');
+    //tripal_set_default_cv('feature_relationship', 'type_id', 'feature_relationship');
 
     /////////////////////////////////////////////////////////////////////////////
     //                            Chado Map Module
@@ -241,9 +241,9 @@ function tripal_chado_prepare_chado() {
     tripal_featuremap_add_cvterms();
 
     // set the default vocabularies
-    tripal_set_default_cv('featuremapprop', 'type_id', 'featuremap_property');
-    tripal_set_default_cv('featureposprop', 'type_id', 'featurepos_property');
-    tripal_set_default_cv('featuremap', 'unittype_id', 'featuremap_units');
+    //tripal_set_default_cv('featuremapprop', 'type_id', 'featuremap_property');
+    //tripal_set_default_cv('featureposprop', 'type_id', 'featurepos_property');
+    //tripal_set_default_cv('featuremap', 'unittype_id', 'featuremap_units');
 
     /////////////////////////////////////////////////////////////////////////////
     //                          Chado Library Module
@@ -256,8 +256,8 @@ function tripal_chado_prepare_chado() {
     tripal_library_add_cvterms();
 
     // set the default vocabularies
-    tripal_set_default_cv('libraryprop', 'type_id', 'library_property');
-    tripal_set_default_cv('library', 'type_id', 'library_type');
+    //tripal_set_default_cv('libraryprop', 'type_id', 'library_property');
+    //tripal_set_default_cv('library', 'type_id', 'library_type');
 
     /////////////////////////////////////////////////////////////////////////////
     //                          Chado NatDiv Module
@@ -272,8 +272,8 @@ function tripal_chado_prepare_chado() {
     tripal_project_add_cvterms();
 
     // set the default vocabularies
-    tripal_set_default_cv('projectprop', 'type_id', 'project_property');
-    tripal_set_default_cv('project_relationship', 'type_id', 'project_relationship');
+    //tripal_set_default_cv('projectprop', 'type_id', 'project_property');
+    ///tripal_set_default_cv('project_relationship', 'type_id', 'project_relationship');
 
     /////////////////////////////////////////////////////////////////////////////
     //                          Chado Pub Module
@@ -295,9 +295,9 @@ function tripal_chado_prepare_chado() {
     tripal_pub_add_custom_tables();
 
     // set the default vocabularies
-    tripal_set_default_cv('pub', 'type_id', 'tripal_pub');
-    tripal_set_default_cv('pubprop', 'type_id', 'tripal_pub');
-    tripal_set_default_cv('pub_relationship', 'type_id', 'pub_relationship');
+    //tripal_set_default_cv('pub', 'type_id', 'tripal_pub');
+    //tripal_set_default_cv('pubprop', 'type_id', 'tripal_pub');
+    //tripal_set_default_cv('pub_relationship', 'type_id', 'pub_relationship');
 
     // Add the supported loaders
     variable_set('tripal_pub_supported_dbs', array('PMID', 'AGL'));
@@ -309,9 +309,9 @@ function tripal_chado_prepare_chado() {
     tripal_stock_add_cvs();
 
     // set the default vocabularies
-    tripal_set_default_cv('stock', 'type_id', 'stock_type');
-    tripal_set_default_cv('stockprop', 'type_id', 'stock_property');
-    tripal_set_default_cv('stock_relationship', 'type_id', 'stock_relationship');
+    //tripal_set_default_cv('stock', 'type_id', 'stock_type');
+    //tripal_set_default_cv('stockprop', 'type_id', 'stock_property');
+    //tripal_set_default_cv('stock_relationship', 'type_id', 'stock_relationship');
 
     // add the materialized view
     tripal_stock_add_organism_count_mview();
@@ -366,11 +366,11 @@ function tripal_chado_prepare_chado() {
       'definition' => 'The way in which two things are connected.',
       'cv_name' => 'local',
     ));
-    
+
     tripal_insert_cvterm(array(
       'id' => 'local:biomaterial',
       'name' => 'biomaterial',
-      'definition' => 'A biomaterial represents the MAGE concept of BioSource, BioSample, ' . 
+      'definition' => 'A biomaterial represents the MAGE concept of BioSource, BioSample, ' .
         'and LabeledExtract. It is essentially some biological material (tissue, cells, serum) that ' .
         'may have been processed. Processed biomaterials should be traceable back to raw ' .
         'biomaterials via the biomaterialrelationship table.',
@@ -410,21 +410,21 @@ function tripal_chado_prepare_chado() {
     // Create the 'Organism' entity type. This uses the obi:organism term.
     $error = '';
     if (!tripal_create_bundle('OBI', '0100026', 'organism', $error)) {
-      throw new Exception($error);
+      throw new Exception($error['!message']);
     }
 
     // Create the 'Analysis' entity type. This uses the local:analysis term.
     $error = '';
     if (!tripal_create_bundle('local', 'analysis', 'analysis', $error)) {
-      throw new Exception($error);
+      throw new Exception($error['!message']);
     }
 
     // Create the 'Project' entity type. This uses the local:project term.
     $error = '';
     if (!tripal_create_bundle('local', 'project', 'project', $error)) {
-      throw new Exception($error);
+      throw new Exception($error['!message']);
     }
-    
+
     // Initialize the population of the tripal_cvterm_mapping table.
     tripal_chado_map_cvterms();
 

+ 41 - 0
tripal_chado/includes/tripal_chado.vocab_storage.inc

@@ -58,6 +58,47 @@ function tripal_chado_vocab_get_term($vocabulary, $accession) {
   return $term;
 }
 
+/**
+ * Implements hook_vocab_add_term().
+ *
+ * This hook is created by the Tripal module and is not a Drupal hook.
+ */
+function tripal_chado_vocab_add_term($details) {
+  $vocabulary = $details['vocab']['name'];
+  $accession = $details['accession'];
+
+  // First check to make sure the term doesn't already exist
+  $term = tripal_chado_vocab_get_term($vocabulary, $accession);
+  if ($term) {
+    return TRUE;
+  }
+
+  // First make sure the vocabulary is added.
+  $values = array(
+    'name' => $vocabulary,
+    'description' => $details['vocab']['description'],
+    'url' => $details['vocab']['url'],
+    // TODO: deal with the URL prefix
+  );
+  $options = array('update_existing' => TRUE);
+  tripal_insert_db($values, $options);
+
+
+  // Second make sure the term is added.
+  $term = tripal_insert_cvterm(array(
+    'id' => $vocabulary . ':' . $accession,
+    'name' => $details['name'],
+    'definition' => $details['definition'],
+    'cv_name' => $details['vocab']['name'],
+  ));
+
+  // Return TRUE on success.
+  if (!$term) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
 /**
  * Implements hook_vocab_import_form();
  */

+ 36 - 36
tripal_chado/tripal_chado.module

@@ -586,42 +586,42 @@ function tripal_chado_theme($existing, $type, $theme, $path) {
   $themes = array(
 
     // Theme fields.
-    'chado_base__dbxref_id_widget' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_base__dbxref_id.inc',
-    ),
-    'chado_linker__dbxref_widget' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_linker__dbxref.inc',
-    ),
-    'chado_linker__cvterm_widget' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_linker__cvterm.inc',
-    ),
-    'chado_linker__synonym_widget' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_linker__synonym.inc',
-    ),
-    'chado_linker__relationship_widget' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_linker__relationship.inc',
-    ),
-    'chado_linker__relationship_instance_settings' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_linker__relationship.inc',
-    ),
-    'chado_linker__pub_widget' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_linker__pub.inc',
-    ),
-    'chado_linker__contact_widget' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_linker__contact.inc',
-    ),
-    'chado_linker__prop_adder_widget' => array(
-      'render element' => 'element',
-      'file' => 'includes/TripalFields/chado_linker__prop_adder.inc',
-    ),
+     'data__accession_widget' => array(
+       'render element' => 'element',
+       'file' => 'includes/TripalFields/data__accession_widget.inc',
+     ),
+//     'chado_linker__dbxref_widget' => array(
+//       'render element' => 'element',
+//       'file' => 'includes/TripalFields/chado_linker__dbxref.inc',
+//     ),
+//     'chado_linker__cvterm_widget' => array(
+//       'render element' => 'element',
+//       'file' => 'includes/TripalFields/chado_linker__cvterm.inc',
+//     ),
+//     'chado_linker__synonym_widget' => array(
+//       'render element' => 'element',
+//       'file' => 'includes/TripalFields/chado_linker__synonym.inc',
+//     ),
+//     'chado_linker__relationship_widget' => array(
+//       'render element' => 'element',
+//       'file' => 'includes/TripalFields/chado_linker__relationship.inc',
+//     ),
+//     'chado_linker__relationship_instance_settings' => array(
+//       'render element' => 'element',
+//       'file' => 'includes/TripalFields/chado_linker__relationship.inc',
+//     ),
+//     'chado_linker__pub_widget' => array(
+//       'render element' => 'element',
+//       'file' => 'includes/TripalFields/chado_linker__pub.inc',
+//     ),
+//     'chado_linker__contact_widget' => array(
+//       'render element' => 'element',
+//       'file' => 'includes/TripalFields/chado_linker__contact.inc',
+//     ),
+//     'chado_linker__prop_adder_widget' => array(
+//       'render element' => 'element',
+//       'file' => 'includes/TripalFields/chado_linker__prop_adder.inc',
+//     ),
     'tripal_chado_date_combo' => array(
       'render element' => 'element',
       'file' => 'theme/tripal_chado.theme.inc',