Browse Source

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

Stephen Ficklin 7 years ago
parent
commit
16838d4914
28 changed files with 498 additions and 79 deletions
  1. 166 0
      tripal/api/tripal.entities.api.inc
  2. 28 19
      tripal/includes/tripal.bulk_update.inc
  3. 5 1
      tripal/includes/tripal.importer.inc
  4. 10 43
      tripal/tripal.drush.inc
  5. 11 1
      tripal_chado/includes/TripalFields/chado_linker__contact/chado_linker__contact.inc
  6. 2 0
      tripal_chado/includes/TripalFields/data__protein_sequence/data__protein_sequence.inc
  7. 2 0
      tripal_chado/includes/TripalFields/data__sequence/data__sequence.inc
  8. 3 0
      tripal_chado/includes/TripalFields/data__sequence_checksum/data__sequence_checksum.inc
  9. 17 0
      tripal_chado/includes/TripalFields/data__sequence_coordinates/data__sequence_coordinates.inc
  10. 2 1
      tripal_chado/includes/TripalFields/data__sequence_length/data__sequence_length.inc
  11. 2 0
      tripal_chado/includes/TripalFields/go__gene_expression/go__gene_expression.inc
  12. 11 1
      tripal_chado/includes/TripalFields/local__contact/local__contact.inc
  13. 11 0
      tripal_chado/includes/TripalFields/local__source_data/local__source_data.inc
  14. 18 2
      tripal_chado/includes/TripalFields/obi__organism/obi__organism.inc
  15. 26 0
      tripal_chado/includes/TripalFields/ogi__location_on_map/ogi__location_on_map.inc
  16. 5 0
      tripal_chado/includes/TripalFields/operation__phylotree_vis/operation__phylotree_vis.inc
  17. 11 0
      tripal_chado/includes/TripalFields/sbo__database_cross_reference/sbo__database_cross_reference.inc
  18. 2 0
      tripal_chado/includes/TripalFields/sbo__phenotype/sbo__phenotype.inc
  19. 30 2
      tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship.inc
  20. 2 0
      tripal_chado/includes/TripalFields/schema__publication/schema__publication.inc
  21. 17 2
      tripal_chado/includes/TripalFields/sio__annotation/sio__annotation.inc
  22. 2 0
      tripal_chado/includes/TripalFields/sio__references/sio__references.inc
  23. 2 0
      tripal_chado/includes/TripalFields/so__cds/so__cds.inc
  24. 11 0
      tripal_chado/includes/TripalFields/so__genotype/so__genotype.inc
  25. 14 0
      tripal_chado/includes/TripalFields/so__transcript/so__transcript.inc
  26. 15 1
      tripal_chado/includes/TripalFields/taxrank__infraspecific_taxon/taxrank__infraspecific_taxon.inc
  27. 2 2
      tripal_chado/includes/TripalImporter/OBOImporter.inc
  28. 71 4
      tripal_ws/includes/TripalWebService/TripalEntityService_v0_1.inc

+ 166 - 0
tripal/api/tripal.entities.api.inc

@@ -1121,3 +1121,169 @@ function tripal_entity_label($entity) {
   }
   return NULL;
 }
+
+function tripal_get_bundle_details($bundle_name) {
+  global $user;
+
+  $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
+  $term = tripal_load_term_entity(array('term_id' => $bundle->term_id));
+  $vocab = $term->vocab;
+  $instances = field_info_instances('TripalEntity', $bundle->name);
+
+  $details = array(
+    'name' => $bundle->name,
+    'label' => $bundle->label,
+    'term' => array(
+      'accession' => $vocab->vocabulary . ':' . $term->accession,
+      'name' => $term->name,
+      'definition' => $term->definition,
+      'url' => $term->url
+    ),
+    'fields' => array(),
+  );
+
+  // Iterate through each feild and provide a discription of it and
+  // it's sub elements.
+  foreach ($instances as $instance) {
+    // Skip deleted fields.
+    if ($instance['deleted']) {
+      continue;
+    }
+
+    $field_name = $instance['field_name'];
+    $field = field_info_field($field_name);
+
+    $field_class = $field['type'];
+    $term_vocab = $instance['settings']['term_vocabulary'];
+    $term_accession = $instance['settings']['term_accession'];
+    $field_term = tripal_get_term_details($term_vocab, $term_accession);
+    $field_details = array(
+      'name' => $field_name,
+      'label' => $instance['label'],
+      'term' => array(
+        'accession' => $term_vocab . ":" . $term_accession,
+        'name' => $field_term['name'],
+        'definition' => $field_term['definition'],
+        'url' => $field_term['url'],
+      ),
+      // These items can be overridden by the element_info array that
+      // is present in a TripalField instance.  Here we set defaults.
+      'required' => $instance['required'] ? TRUE : FALSE,
+      'type' => 'xs:string',
+      'readonly' => TRUE,
+      // The cardinatlity value always comes from the field.
+      'cardinality' => $field['cardinality'],
+    );
+
+    if (tripal_load_include_field_class($field_class)) {
+      $field_obj = new $field_class($field, $instance);
+      $element_info = $field_obj->elementInfo();
+      $element_info = $element_info[$term_vocab . ':' . $term_accession];
+
+      // If the element info for this field sets required, type and readonly
+      // attributes then set those.
+      $field_details['required'] = array_key_exists('required', $element_info) ? $element_info['required'] : FALSE;
+      $field_details['type'] = array_key_exists('type', $element_info) ? $element_info['type'] : 'xs:string';
+      $field_details['readonly'] = array_key_exists('readonly', $element_info) ? $element_info['readonly'] : TRUE;
+      $field_details['label'] = array_key_exists('label', $element_info) ? $element_info['label'] : $field_details['label'];
+      $field_details['help'] = array_key_exists('help', $element_info) ? $element_info['help'] : '';
+
+      // If this field is an 'xs:complexType' then it will have sub elements.
+      // we need to add those as well.
+      if (array_key_exists('elements', $element_info) and is_array($element_info['elements'])) {
+        _tripal_get_bundle_field_element_details($element_info['elements'], $field_details);
+      }
+      $details['fields'][] = $field_details;
+    }
+
+  }
+  return $details;
+}
+/**
+ * A recursive helper function for the tripal_get_bundle_details.
+ *
+ * @param $elementInfo
+ */
+function _tripal_get_bundle_field_element_details($elements, &$field_details) {
+   $field_details['elements'] = array();
+   foreach ($elements as $element_key => $element_info) {
+     // Handle the entity element differnetly.
+     if ($element_key == 'entity') {
+       continue;
+     }
+     list($term_vocab, $term_accession) = explode(':', $element_key);
+     $term = tripal_get_term_details($term_vocab, $term_accession);
+
+     $element_details = array(
+       'name' => $element_info['name'],
+       'label' => array_key_exists('label', $element_info) ? $element_info['label'] : ucfirst(preg_replace('/_/', ' ', $term['name'])),
+       'help' => array_key_exists('help', $element_info) ? $element_info['help'] : '',
+       'term' => array(
+         'accession' => $term_vocab . ':' . $term_accession,
+         'name' => $term['name'],
+         'definition' => $term['definition'],
+         'url' => $term['url'],
+       ),
+       'required' => array_key_exists('required', $element_info) ? $element_info['required'] : FALSE,
+       'type' => array_key_exists('type', $element_info) ? $element_info['type'] : 'xs:string',
+       'readonly' => array_key_exists('readonly', $element_info) ? $element_info['readonly'] : TRUE,
+     );
+     if (array_key_exists('elements', $element_info) and is_array($element_info['elements'])) {
+       _tripal_get_bundle_field_element_details($element_info['elements'], $element_details);
+     }
+     $field_details['elements'][] = $element_details;
+   }
+}
+
+function tripal_insert_entity($bundle_name, $values){
+  global $user;
+
+  $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
+
+  // Get the fields associated with this content type.
+  $instances = field_info_instances('TripalEntity', $bundle->name);
+
+  foreach ($instances as $instance) {
+    $field_name = $instance['field_name'];
+    $field = field_info_field($field_name);
+    $field_type = $field['type'];
+    $field_settings = $field['settings'];
+    $instance_settings = $instance['settings'];
+    $field_name = $field['field_name'];
+    $vocabulary = $instance['settings']['term_vocabulary'];
+    $accession = $instance['settings']['term_accession'];
+    $field_accession = $vocabulary . ':' . $accession;
+    $field_term = tripal_get_term_details($vocabulary, $accession);
+    $field_key = $field_term['name'];
+    $field_key = strtolower(preg_replace('/ /', '_', $key));
+
+    // There are three ways that a field value can be specified. Those
+    // are as the controlled vocabulary accession (e.g. GO:0000134), sa
+    // the field name or as the field key which is the term name with
+    // spaces replaced with underscores.
+    // First make sure that required fields are present.
+    if ($instance['required'] == TRUE) {
+      if (!array_key_exists($field_key, $values) and
+          !array_key_exists($field_accession, $values) and
+          !array_key_exists($field_name, $values)) {
+        throw new Exception(t('Cannot insert the record. Missing the required field "%missing".',
+          array('%missing' => $field_name)));
+      }
+    }
+  }
+
+  // Make sure that all required fields are presnet
+
+  // TODO: make sure the user has permission to do this.
+  $ec = entity_get_controller('TripalEntity');
+  $entity = $ec->create(array(
+    'bundle' => $bundle_name,
+    'term_id' => $bundle->term_id,
+  ));
+  $entity = $entity->save();
+}
+
+function tripal_update_entity($bundle_name, $values) {
+
+
+}

+ 28 - 19
tripal/includes/tripal.bulk_update.inc

@@ -1,35 +1,44 @@
 <?php
+
 /**
  * Updates all existing url aliases for an entity.
  *
  * @param $bundle_id
  * @param $update
  * @param $type
-*/
+ */
 function tripal_update_all($bundle_id, $update, $type) {
-  //Load all the entity_ids.
+  // Load all the entity_ids.
   $entity_table = 'chado_'.$bundle_id;
   $entities = db_select($entity_table, 'e')
-  ->fields('e', array('entity_id'))
-  ->execute()->fetchAll();
+    ->fields('e', array('entity_id'))
+    ->execute()->fetchAll();
   $num_entities = count($entities);
-  //Parse the $update variable for tokens and load those tokens.
+  // Parse the $update variable for tokens and load those tokens.
   preg_match_all("/\[[^\]]*\]/", $update, $bundle_tokens);
-  //Get the queue so we can add to it.  Use a
-  //descriptive name. It's ok if it doesn't exist yet.
+  // Get the queue so we can add to it.  Use a
+  // descriptive name. It's ok if it doesn't exist yet.
   $queue = DrupalQueue::get('entityQueue');
-  //Push all the items into the queue, one at a time.
-  //You can push any data in with (arrays, objects, etc).
-  foreach($entities as $entity) {
+  // Push all the items into the queue, one at a time.
+  // You can push any data in with (arrays, objects, etc).
+  foreach ($entities as $entity) {
     $queue->createItem($entity);
   }
+  $fields = array();
+  foreach ($bundle_tokens as $bundle_token) {
+    foreach ($bundle_token as $token) {
+      $string = str_replace(array('[', ']'), '', $token);
+      $field_array = field_info_field($string);
+      $fields[] = $field_array['id'];
+    }
+  }
   $i = 0;
-  //Pull items out one at a time.
-  while($entity = $queue->claimItem()) {
-    $arg = tripal_load_entity('TripalEntity', [$entity->data->entity_id], $bundle_tokens);
+  // Pull items out one at a time.
+  while ($entity = $queue->claimItem()) {
+    $arg = tripal_load_entity('TripalEntity', [$entity->data->entity_id], FALSE, $fields);
     if ($type == 'alias') {
       if (!empty($arg)) {
-        if(is_array($arg)){
+        if (is_array($arg)) {
           $ent = reset($arg);
         }
         // Get the entity controller and clear the cache if requested (default).
@@ -39,20 +48,20 @@ function tripal_update_all($bundle_id, $update, $type) {
     }
     elseif ($type == 'title') {
       if (!empty($arg)) {
-        if(is_array($arg)){
+        if (is_array($arg)) {
           $ent = reset($arg);
         }
+
         $ec = entity_get_controller('TripalEntity');
         $ec->setTitle($ent, $update);
       }
     }
     $i++;
     // Check if 50 items have been updated, if so print message.
-    if ($i < $num_entities){
-      print $i."/".$num_entities." entities have been updated.\r";
+    if ($i < $num_entities) {
+      print $i . "/" . $num_entities . " entities have been updated.\r";
     }
-    //Good, we succeeded.  Delete the item as it is no longer needed.
+    // Good, we succeeded.  Delete the item as it is no longer needed.
     $queue->deleteItem($entity);
   }
 }
-

+ 5 - 1
tripal/includes/tripal.importer.inc

@@ -160,7 +160,6 @@ function tripal_get_importer_form_submit($form, &$form_state) {
   unset($run_args['op']);
   unset($run_args['button']);
 
-
   $file_local = NULL;
   $file_upload = NULL;
   $file_remote = NULL;
@@ -195,6 +194,11 @@ function tripal_get_importer_form_submit($form, &$form_state) {
     // Now allow the loader to do it's own submit if needed.
     $importer = new $class();
     $importer->formSubmit($form, $form_state);
+    // If the formSubmit made changes to the $form_state we need to update the
+    // $run_args info.
+    if ($run_args !== $form_state['values']) {
+      $run_args = $form_state['values'];
+    }
 
     // If the importer wants to rebuild the form for some reason then let's
     // not add a job.

+ 10 - 43
tripal/tripal.drush.inc

@@ -115,14 +115,14 @@ function tripal_drush_command() {
     'description' => dt('Prepares a new Tripal installation with content types, requires the username of an administrator to run.'),
     'arguments'   => array(),
     'examples' => array(
-      'Standard example' => 'drush trp-prepare-chado --username=administrator',
+      'Standard example' => 'drush trp-prepare-chado --user=administrator',
     ),
   );
   $items['trp-set-permissions'] = array(
     'description' => dt('Gives view, edit, delete, create priveleges to administrators for all tripal content types.'),
     'arguments'   => array(),
     'examples' => array(
-      'Standard example' => 'drush trp-set-permissions --username=administrator',
+      'Standard example' => 'drush trp-set-permissions --user=administrator',
     ),
   );
   return $items;
@@ -371,49 +371,16 @@ function drush_tripal_trp_set_permissions() {
   }
 
   drush_tripal_set_user($username);
-
-  $database_info = FALSE;
-  while (!$database_info) {
-    drush_print(dt(""));
-    drush_print(dt(
-      "To add permissions from the command line the database information is required, please have the database host (127.0.0.1 or localhost), database name, postgres username and postgres user password ready.\n"
-    ));
-    print_r("");
-    $host = drush_prompt(dt('host, like localhost or 127.0.0.1'));
-    $database = drush_prompt(dt('database name'));
-    $postgres_username = drush_prompt(dt('postgres username'));
-    $postgres_password = drush_prompt(dt('postgres password'));
-    drush_print(dt(""));
-    drush_print(dt(
-    "This is the information provided, please review and confirm it is correct:
-     Database host: $host
-     Database name: $database
-     Database username: $postgres_username
-     Database user password: $postgres_password
-     "
-    ));
-    $database_info = drush_confirm(dt('Is this information correct?'));
-  }
-  print_r("Adding permissions for the administrator to view, edit, create, and delete all the newly created content types.\n");
   $permissions = array();
-  $bundles = array();
-  $conn = pg_pconnect("host=$host dbname=$database user=$postgres_username password=$postgres_password");
-  if (!$conn) {
-    echo "An error occurred when attempting to perimssion the administrator. Please navigate to your new site and add permissions to your new content types here admin/people/permissions.\n";
-    exit;
-  }
-  $result = pg_query($conn, "SELECT name FROM tripal_bundle");
-  if (!$result) {
-    echo "An error occurred.\n";
-    exit;
-  }
-
-  while ($row = pg_fetch_row($result)) {
-    array_push($bundles, $row);
-  }
+  $bundles =
+  db_select('tripal_bundle', 'TB')
+    ->fields('TB', array('name'))
+    ->execute()
+    ->fetchAll();
+  print_r($bundles);
   foreach ($bundles as $bundles => $bundle) {
-    array_push($permissions, ' view ' . $bundle[0], ' create ' . $bundle[0],
-      ' edit ' . $bundle[0], ' delete ' . $bundle[0]);
+    array_push($permissions, ' view ' . $bundle->name, ' create ' . $bundle->name,
+      ' edit ' . $bundle->name, ' delete ' . $bundle->name);
   }
   $string_permissions = implode(",", $permissions);
   $args4 = array('administrator', $string_permissions);

+ 11 - 1
tripal_chado/includes/TripalFields/chado_linker__contact/chado_linker__contact.inc

@@ -72,7 +72,8 @@ class chado_linker__contact extends ChadoField {
         'operations' => array('eq', 'contains', 'starts'),
         'sortable' => TRUE,
         'searchable' => TRUE,
-        'type' => 'string',
+        'type' => 'xs:complexType',
+        'readonly' => FALSE,
         'elements' => array(
           $type_term => array(
             'searchable' => TRUE,
@@ -80,6 +81,9 @@ class chado_linker__contact extends ChadoField {
             'help' => 'The type of contact',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $name_term => array(
             'searchable' => TRUE,
@@ -87,6 +91,9 @@ class chado_linker__contact extends ChadoField {
             'help' => 'The name of the contact.',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $description_term => array(
             'searchable' => TRUE,
@@ -94,6 +101,9 @@ class chado_linker__contact extends ChadoField {
             'help' => 'A descriptoin of the contact.',
             'operations' => array('contains'),
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           'entity' => array(
             'searchable' => FALSE,

+ 2 - 0
tripal_chado/includes/TripalFields/data__protein_sequence/data__protein_sequence.inc

@@ -62,6 +62,8 @@ class data__protein_sequence extends ChadoField {
         'help' => 'The polypeptide sequence derived from mRNA',
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:string',
+        'readonly' => FALSE,
       ),
     );
     return $info;

+ 2 - 0
tripal_chado/includes/TripalFields/data__sequence/data__sequence.inc

@@ -61,6 +61,8 @@ class data__sequence extends ChadoField {
         'operations' => array(),
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:string',
+        'readonly' => FALSE,
       ),
     );
   }

+ 3 - 0
tripal_chado/includes/TripalFields/data__sequence_checksum/data__sequence_checksum.inc

@@ -64,6 +64,9 @@ class data__sequence_checksum extends ChadoField {
         'operations' => array(),
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:string',
+        'readonly' => TRUE,
+        'required' => FALSE,
       ),
     );
   }

+ 17 - 0
tripal_chado/includes/TripalFields/data__sequence_coordinates/data__sequence_coordinates.inc

@@ -74,6 +74,8 @@ class data__sequence_coordinates extends ChadoField {
         'searchable' => FALSE,
         'label' => 'Location Coordinates',
         'help' => 'The locations on other genomic sequences where this record has been aligned.',
+        'type' => 'xs:complexType',
+        'readonly' => TRUE,
         'elements' => array(
           $reference_term => array(
             'searchable' => TRUE,
@@ -81,6 +83,9 @@ class data__sequence_coordinates extends ChadoField {
             'help' => 'The genomic feature on which this feature is localized.',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           $fmin_term => array(
             'searchable' => TRUE,
@@ -89,6 +94,9 @@ class data__sequence_coordinates extends ChadoField {
             'type' => 'numeric',
             'operations' => array('eq', 'gt', 'lt', 'gte' ,'lte'),
             'sortable' => TRUE,
+            'type' => 'xs:integer',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           $fmax_term => array(
             'searchable' => TRUE,
@@ -97,6 +105,9 @@ class data__sequence_coordinates extends ChadoField {
             'type' => 'numeric',
             'operations' => array('eq', 'gt', 'lt', 'gte' ,'lte'),
             'sortable' => TRUE,
+            'type' => 'xs:integer',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           $phase_term => array(
             'searchable' => TRUE,
@@ -105,6 +116,9 @@ class data__sequence_coordinates extends ChadoField {
             'help' => 'The phase of the feature (applicable only to coding sequences).',
             'operations' => array('eq', 'gt', 'lt', 'gte' ,'lte'),
             'sortable' => TRUE,
+            'type' => 'xs:integer',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           $strand_term => array(
             'searchable' => TRUE,
@@ -112,6 +126,9 @@ class data__sequence_coordinates extends ChadoField {
             'help' => 'The orientation of this feature where it is localized',
             'operations' => array('eq', 'gt', 'lt', 'gte' ,'lte'),
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
         ),
       ),

+ 2 - 1
tripal_chado/includes/TripalFields/data__sequence_length/data__sequence_length.inc

@@ -65,7 +65,8 @@ class data__sequence_length extends ChadoField {
         'operations' => array('eq', 'gt', 'lt', 'gte', 'lte'),
         'sortable' => TRUE,
         'searchable' => TRUE,
-        'type' => 'numeric',
+        'type' => 'xs:integer',
+        'readonly' => TRUE,
       ),
     );
   }

+ 2 - 0
tripal_chado/includes/TripalFields/go__gene_expression/go__gene_expression.inc

@@ -70,6 +70,8 @@ class go__gene_expression extends ChadoField {
         'operations' => array(),
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:string',
+        'readonly' => TRUE,
       ),
     );
   }

+ 11 - 1
tripal_chado/includes/TripalFields/local__contact/local__contact.inc

@@ -70,7 +70,8 @@ class local__contact extends ChadoField {
         'operations' => array('eq', 'contains', 'starts'),
         'sortable' => TRUE,
         'searchable' => TRUE,
-        'type' => 'string',
+        'type' => 'xs:complexType',
+        'readonly' => TRUE,
         'elements' => array(
           $type_term => array(
             'searchable' => TRUE,
@@ -78,6 +79,9 @@ class local__contact extends ChadoField {
             'help' => 'The type of contact',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $name_term => array(
             'searchable' => TRUE,
@@ -85,6 +89,9 @@ class local__contact extends ChadoField {
             'help' => 'The name of the contact.',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $description_term => array(
             'searchable' => TRUE,
@@ -92,6 +99,9 @@ class local__contact extends ChadoField {
             'help' => 'A descriptoin of the contact.',
             'operations' => array('contains'),
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => FALSE,
           ),
           'entity' => array(
             'searchable' => FALSE,

+ 11 - 0
tripal_chado/includes/TripalFields/local__source_data/local__source_data.inc

@@ -70,24 +70,35 @@ class local__source_data extends ChadoField {
         'operations' => array(),
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:complexType',
+        'readonly' => TRUE,
         'elements' => array(
           $sourcename_term => array(
             'searchable' => TRUE,
             'label' => 'Data Source Name',
             'help' => 'The name of the data source used for the analysis.',
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           $sourceversion_term => array(
             'searchable' => TRUE,
             'label' => 'Data Source Version',
             'help' => 'If applicable, the version number of the source data used for the analysis.',
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           $sourceuri_term => array(
             'searchable' => FALSE,
             'label' => 'Data Source URI',
             'help' => 'If applicable, the universal resource indicator (e.g. URL) of the source data used for the analysis.',
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
         ),
       ),

+ 18 - 2
tripal_chado/includes/TripalFields/obi__organism/obi__organism.inc

@@ -221,43 +221,59 @@ class obi__organism extends ChadoField {
         'operations' => array('eq', 'contains', 'starts'),
         'sortable' => TRUE,
         'searchable' => TRUE,
-        'type' => 'string',
+        'readonly' => FALSE,
+        'type' => 'xs:complexType',
         'elements' => array(
           'rdfs:label' => array(
             'searchable' => TRUE,
             'name' => 'scientfic_name',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           $genus_term => array(
             'searchable' => TRUE,
             'name' => 'genus',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'readonly' => FALSE,
+            'type' => 'xs:string',
+            'required' => TRUE,
           ),
           $species_term => array(
             'searchable' => TRUE,
             'name' => 'species',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'readonly' => FALSE,
+            'type' => 'xs:string',
+            'required' => TRUE,
           ),
           $infraspecific_name_term => array(
             'searchable' => TRUE,
             'name' => 'infraspecies',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'readonly' => FALSE,
+            'type' => 'xs:string',
+            'required' => FALSE,
           ),
           $infraspecific_type_term => array(
             'searchable' => TRUE,
             'name' => 'infraspecific_type',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'readonly' => FALSE,
+            'type' => 'xs:integer',
+            'required' => FALSE,
           ),
           'entity' => array(
             'searchable' => FALSE,
           ),
         ),
-      )
+      ),
     );
   }
 

+ 26 - 0
tripal_chado/includes/TripalFields/ogi__location_on_map/ogi__location_on_map.inc

@@ -73,22 +73,33 @@ class ogi__location_on_map extends ChadoField {
       $field_term => array(
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:complexType',
+        'readonly' => TRUE,
         'elements' => array(
           $map_term => array(
             'searchable' => FALSE,
             'sortable' => FALSE,
+            'type' => 'xs:complexType',
+            'readonly' => TRUE,
+            'required' => FALSE,
             'elements' => array(
               $name_term => array(
                 'label' => 'Map Name',
                 'help' => 'The name of the map.',
                 'searchable' => TRUE,
                 'sortable' => TRUE,
+                'type' => 'xs:string',
+                'readonly' => TRUE,
+                'required' => FALSE,
               ),
               $description_term => array(
                 'label' => 'Map Description',
                 'help' => 'A description of the map.',
                 'searchable' => TRUE,
                 'sortable' => FALSE,
+                'type' => 'xs:string',
+                'readonly' => TRUE,
+                'required' => FALSE,
               ),
               'entity' => array(
                 'searchable' => FALSE,
@@ -99,24 +110,36 @@ class ogi__location_on_map extends ChadoField {
           $ref_feature_term => array(
             'searchable' => FALSE,
             'sortable' => FALSE,
+            'type' => 'xs:complexType',
+            'readonly' => TRUE,
+            'required' => FALSE,
             'elements' => array(
               $ref_feature_name => array(
                 'label' => 'Map Reference Feature Name',
                 'help' => 'The genomic or genetic feature Nameof the map on which this feature is mapped.',
                 'searchable' => TRUE,
                 'sortable' => TRUE,
+                'type' => 'xs:string',
+                'readonly' => TRUE,
+                'required' => FALSE,
               ),
               $ref_feature_id=> array(
                 'label' => 'Map Reference Feature Identifier',
                 'help' => 'The genomic or genetic feature of the map on which this feature is mapped.',
                 'searchable' => TRUE,
                 'sortable' => TRUE,
+                'type' => 'xs:string',
+                'readonly' => TRUE,
+                'required' => FALSE,
               ),
               $ref_feature_type=> array(
                 'label' => 'Map Reference Feature Type',
                 'help' => 'The type of genomic or genetic feature of the map on which this feature is mapped.',
                 'searchable' => TRUE,
                 'sortable' => TRUE,
+                'type' => 'xs:string',
+                'readonly' => TRUE,
+                'required' => FALSE,
               ),
             ),
           ),
@@ -125,6 +148,9 @@ class ogi__location_on_map extends ChadoField {
             'help' => 'Maps may use different coordinate systems. This indicates the type of coordinate.',
             'searchable' => TRUE,
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
         ),
       ),

+ 5 - 0
tripal_chado/includes/TripalFields/operation__phylotree_vis/operation__phylotree_vis.inc

@@ -94,9 +94,14 @@ class operation__phylotree_vis extends ChadoField {
         'sortable' => FALSE,
         'searchable' => FALSE,
         'type' => 'string',
+        'type' => 'xs:complexType',
+        'readonly' => TRUE,
         'elements' => array(
           'schema:url' => array(
             'searchabel' => FALSE,
+            'type' => 'xs:anyURI',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
         ),
       )

+ 11 - 0
tripal_chado/includes/TripalFields/sbo__database_cross_reference/sbo__database_cross_reference.inc

@@ -73,24 +73,35 @@ class sbo__database_cross_reference extends ChadoField {
         'label' => 'Cross Reference',
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:complexType',
+        'readonly' => FALSE,
         'elements' => array(
           $dbname_term => array(
             'searchable' => TRUE,
             'label' => 'Cross Reference Database Name',
             'help' => 'The name of the remote database that houses the cross reference.',
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $accession_term => array(
             'searchable' => TRUE,
             'label' => 'Cross Reference Database Accession',
             'help' => 'The unique accession (identifier) in the database that houses the cross reference.',
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $dburl_term => array(
             'searchable' => FALSE,
             'label' => 'Cross Reference Database URL',
             'help' => 'The URL of the database that houses the cross reference.',
             'sortable' => FALSE,
+            'type' => 'xs:anyURI',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
         ),
       ),

+ 2 - 0
tripal_chado/includes/TripalFields/sbo__phenotype/sbo__phenotype.inc

@@ -67,6 +67,8 @@ class sbo__phenotype extends ChadoField {
         'operations' => array('eq', 'ne', 'contains', 'starts'),
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:string',
+        'readonly' => TRUE,
       ),
     );
   }

+ 30 - 2
tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship.inc

@@ -82,33 +82,49 @@ class sbo__relationship extends ChadoField {
         'operations' => array('eq', 'contains', 'starts'),
         'sortable' => FALSE,
         'searchable' => FALSE,
-        'type' => 'string',
+        'type' => 'xs:complexType',
+        'readonly' => FALSE,
         'elements' => array(
           'SIO:000493' => array(
             'searchable' => FALSE,
+            'name' => 'relationship_clause',
             'label' => 'Relationship Clause',
             'help' => 'An English phrase describing the relationships.',
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           'local:relationship_subject' => array(
             'searchable' => FALSE,
             'name' => 'relationship_subject',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => FALSE,
+            'type' => 'xs:complexType',
+            'readonly' => FALSE,
+            'required' => TRUE,
             'elements' => array(
               'rdfs:type' => array(
+                'name' => 'type',
                 'searchable' => TRUE,
                 'label' => 'Relationship Subject Type',
                 'help' => 'The subject\'s data type in a relationship clause',
                 'operations' => array('eq', 'ne', 'contains', 'starts'),
                 'sortable' => TRUE,
+                'type' => 'xs:string',
+                'readonly' => FALSE,
+                'required' => TRUE,
               ),
               'schema:name' => array(
+                'name' => 'name',
                 'searchable' => TRUE,
                 'label' => 'Relationship Subject Name',
                 'help' => 'The subject\'s name in a relationship clause',
                 'operations' => array('eq', 'ne', 'contains', 'starts'),
                 'sortable' => TRUE,
+                'type' => 'xs:string',
+                'readonly' => FALSE,
+                'required' => TRUE,
               ),
               'entity' => array(
                 'searchable' => FALSE,
@@ -121,12 +137,18 @@ class sbo__relationship extends ChadoField {
             'name' => 'relationship_type',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => TRUE,
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           'local:relationship_object' => array(
             'searchable' => FALSE,
-            'name' => 'species',
+            'name' => 'relationship_object',
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => FALSE,
+            'type' => 'xs:complexType',
+            'readonly' => FALSE,
+            'required' => TRUE,
             'elements' => array(
               'rdfs:type' => array(
                 'searchable' => TRUE,
@@ -135,6 +157,9 @@ class sbo__relationship extends ChadoField {
                 'help' => 'The objects\'s data type in a relationship clause',
                 'operations' => array('eq', 'ne', 'contains', 'starts'),
                 'sortable' => TRUE,
+                'type' => 'xs:string',
+                'readonly' => FALSE,
+                'required' => TRUE,
               ),
               'schema:name' => array(
                 'searchable' => TRUE,
@@ -143,6 +168,9 @@ class sbo__relationship extends ChadoField {
                 'help' => 'The objects\'s name in a relationship clause',
                 'operations' => array('eq', 'ne', 'contains', 'starts'),
                 'sortable' => TRUE,
+                'type' => 'xs:string',
+                'readonly' => FALSE,
+                'required' => TRUE,
               ),
               'entity' => array(
                 'searchable' => FALSE,

+ 2 - 0
tripal_chado/includes/TripalFields/schema__publication/schema__publication.inc

@@ -66,6 +66,8 @@ class schema__publication extends ChadoField {
         'operations' => array(),
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:string',
+        'readonly' => TRUE,
       ),
     );
   }

+ 17 - 2
tripal_chado/includes/TripalFields/sio__annotation/sio__annotation.inc

@@ -102,22 +102,32 @@ class sio__annotation extends ChadoField {
         'operations' => array(),
         'sortable' => FALSE,
         'searchable' => FALSE,
-        'type' => 'array',
+        'type' => 'xs:complexType',
+        'readonly' => FALSE,
         'elements' => array(
           $vocabulary_term => array(
             'sortable' => TRUE,
             'searchable' => TRUE,
             'label' => 'Annotation Term Vocabulary',
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $accession_term => array(
             'sortable' => TRUE,
             'searchable' => TRUE,
             'label' => 'Annotation Term Accession',
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $definition_term => array(
             'sortable' => TRUE,
             'searchable' => TRUE,
             'label' => 'Annotation Term Description',
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => FALSE,
           ),
         ),
       ),
@@ -129,6 +139,9 @@ class sio__annotation extends ChadoField {
         'sortable' => FALSE,
         'searchable' => FALSE,
         'label' => 'Annotation Term Negates',
+        'type' => 'xs:boolean',
+        'readonly' => FALSE,
+        'required' => FALSE,
       );
     }
     if (array_key_exists('rank', $schema['fields'])) {
@@ -137,7 +150,9 @@ class sio__annotation extends ChadoField {
         'sortable' => FALSE,
         'searchable' => FALSE,
         'label' => 'Annotation Term Rank',
-        'type' => 'numeric'
+        'type' => 'xs:integer',
+        'readonly' => FALSE,
+        'required' => FALSE,
       );
     }
     if (array_key_exists('pub_id', $schema['fields'])) {

+ 2 - 0
tripal_chado/includes/TripalFields/sio__references/sio__references.inc

@@ -66,6 +66,8 @@ class sio__references extends ChadoField {
         'operations' => array(),
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:string',
+        'readonly' => TRUE,
       ),
     );
   }

+ 2 - 0
tripal_chado/includes/TripalFields/so__cds/so__cds.inc

@@ -53,6 +53,8 @@ class so__cds extends ChadoField {
       $field_term => array(
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:string',
+        'readonly' => TRUE,
       ),
     );
   }

+ 11 - 0
tripal_chado/includes/TripalFields/so__genotype/so__genotype.inc

@@ -65,24 +65,35 @@ class so__genotype extends ChadoField {
       $field_term => array(
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:complexType',
+        'readonly' => TRUE,
         'elements' => array(
           'rdfs:type' => array(
             'searchable' => FALSE,
             'label' => 'Genotype Type',
             'help' => 'The type of genotype.',
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           'schema:name' => array(
             'label' => 'Genotype Name',
             'help' => 'The name of the genotype.',
             'searchable' => FALSE,
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           'schema:description' => array(
             'label' => 'Genotype Description',
             'help' => 'A description of the genotype.',
             'searchable' => FALSE,
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
         )
       ),

+ 14 - 0
tripal_chado/includes/TripalFields/so__transcript/so__transcript.inc

@@ -64,6 +64,8 @@ class so__transcript extends ChadoField {
         'operations' => array(),
         'sortable' => FALSE,
         'searchable' => FALSE,
+        'type' => 'xs:complexType',
+        'readonly' => TRUE,
         'elements' => array(
           'rdfs:type' => array(
             'name' => 'transcript_type',
@@ -72,6 +74,9 @@ class so__transcript extends ChadoField {
             'searchable' => FALSE,
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           'schema:name' => array(
             'name' => 'transcript_name',
@@ -80,6 +85,9 @@ class so__transcript extends ChadoField {
             'searchable' => FALSE,
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           'data:0842' => array(
             'name' => 'transcript_uniquename',
@@ -88,6 +96,9 @@ class so__transcript extends ChadoField {
             'searchable' => FALSE,
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           'SO:0000735' => array(
             'name' => 'loc',
@@ -96,6 +107,9 @@ class so__transcript extends ChadoField {
             'searchable' => FALSE,
             'operations' => array('eq', 'ne', 'contains', 'starts'),
             'sortable' => FALSE,
+            'type' => 'xs:string',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           'entity' => array(
             'searchable' => FALSE,

+ 15 - 1
tripal_chado/includes/TripalFields/taxrank__infraspecific_taxon/taxrank__infraspecific_taxon.inc

@@ -68,26 +68,40 @@ class taxrank__infraspecific_taxon extends ChadoField {
       $field_term => array(
         'sortable' => FALSE,
         'searchable' => TRUE,
+        'readonly' => FALSE,
+        'type' => 'xs:complexType',
         'elements' => array(
           $label_term => array(
+            'name' => 'label',
             'sortable' => FALSE,
             'searchable' => TRUE,
             'label' => 'Infraspecific Full Name',
             'help' => 'The full infraspecific name including the rank and name.',
+            'type' => 'xsstring',
+            'readonly' => TRUE,
+            'required' => FALSE,
           ),
           $infraspecific_name_term => array(
+            'name' => 'infraspecific_name',
             'sortable' => TRUE,
             'searchable' => TRUE,
             'label' => 'Infrasepcies Name',
             'help' => 'The infraspecific name of the organism below the rank of species.',
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
           $infraspecific_type_term => array(
+            'name' => 'infraspecific_rank',
             'sortable' => TRUE,
             'searchable' => TRUE,
             'label' => 'Infraspecific Rank',
             'help' => 'The infraspecific rank of the organism below the rank of species.',
+            'type' => 'xs:string',
+            'readonly' => FALSE,
+            'required' => TRUE,
           ),
-        )
+        ),
       ),
     );
   }

+ 2 - 2
tripal_chado/includes/TripalImporter/OBOImporter.inc

@@ -267,7 +267,6 @@ class OBOImporter extends TripalImporter {
    * @see TripalImporter::formSubmit()
    */
   public function formSubmit($form, &$form_state) {
-
     $obo_id    = $form_state['values']['obo_id'];
     $obo_name  = trim($form_state['values']['obo_name']);
     $obo_url   = trim($form_state['values']['obo_url']);
@@ -301,8 +300,10 @@ class OBOImporter extends TripalImporter {
           'path' => $obo_url ? $obo_url : $obo_file,
         ))
         ->execute();
+
         // Add the obo_id to the form_state vaules.
         $form_state['values']['obo_id'] = $obo_id;
+
       if ($obo_id) {
         drupal_set_message(t("The vocabulary !vocab has been added.", array('!vocab' => $obo_name)));
       }
@@ -385,7 +386,6 @@ class OBOImporter extends TripalImporter {
   public function run() {
 
     $arguments = $this->arguments['run_args'];
-
     $obo_id = $arguments['obo_id'];
 
     // Make sure the $obo_id is valid

+ 71 - 4
tripal_ws/includes/TripalWebService/TripalEntityService_v0_1.inc

@@ -272,6 +272,11 @@ class TripalEntityService_v0_1 extends TripalWebService {
         // don't add a URL which would make the end-user think they can get
         // that information.
         $items = field_get_items('TripalEntity', $entity, $field_name);
+        $term_key = $this->getContextTerm($term, array('lowercase', 'spacing'));
+        $this->resource->addContextItem($term_key, array(
+          '@id' => $term['url'],
+          '@type' => '@id'
+        ));
         if ($items and count($items) > 0 and $items[0]['value']) {
          $this->addResourceProperty($this->resource, $term, $service_path . '/' . $entity->id . '/' . urlencode($term['name']), array('lowercase', 'spacing'));
         }
@@ -996,7 +1001,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
     // Iterate through the content types and add a class for each one.
     $i = 0;
     while ($bundle = $bundles->fetchObject()) {
-      $entity =  entity_load('TripalTerm', array('id' => $bundle->term_id));
+      $entity = entity_load('TripalTerm', array('id' => $bundle->term_id));
       $term = reset($entity);
       $vocab = $term->vocab;
 
@@ -1059,7 +1064,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
       }
 
       // Add in the properties that correspond to fields in the data.
-      $properties = $this->buildDocBundleFieldProperties($bundle);
+      $properties = $this->addDocBundleFieldProperties($bundle, $term);
 
       $this->addDocClass($details, $operations, $properties);
 
@@ -1072,9 +1077,11 @@ class TripalEntityService_v0_1 extends TripalWebService {
   /**
    * Every content type (bundle) has fields that need to be set as properties.
    */
-  private function buildDocBundleFieldProperties($bundle) {
+  private function addDocBundleFieldProperties($bundle, $bundle_term) {
     $properties = array();
 
+    $content_type_accession = $bundle_term->vocab->vocabulary . ':' . $bundle_term->accession;
+
     $instances = field_info_instances('TripalEntity', $bundle->name);
     foreach ($instances as $instance) {
       // Skip deleted fields.
@@ -1086,6 +1093,8 @@ class TripalEntityService_v0_1 extends TripalWebService {
         continue;
       }
 
+      $accession = $instance['settings']['term_vocabulary'] . ":" . $instance['settings']['term_accession'];
+
       $field_name = $instance['field_name'];
       $field = field_info_field($field_name);
       $field_type = $field['type'];
@@ -1093,8 +1102,66 @@ class TripalEntityService_v0_1 extends TripalWebService {
       if ($field_type == 'remote__data') {
         continue;
       }
+
+      // Check if this field is an auto attach. If not, then we have alink and
+      // we need to indicate that the link has operations.
+      $proptype = $instance['settings']['term_vocabulary'] . ':' . $instance['settings']['term_accession'];
+      if ($instance['settings']['auto_attach'] == FALSE) {
+
+        // Create a WebServiceResource for the hydra:Link type.
+        $id = $content_type_accession . '/' . $accession;
+        $link = new TripalWebServiceResource($this->base_path);
+        $link->setID($accession);
+        $link->setType('hydra:Link');
+        $link->addContextItem('domain', array(
+          "@id" => "rdfs:domain",
+          "@type" => "@id"
+        ));
+        $link->addContextItem('range', array(
+          "@id" => "rdfs:range",
+          "@type" => "@id"
+        ));
+        $link->addContextItem('readable', 'hydra:readable');
+        $link->addContextItem('writeable', 'hydra:writeable');
+        $link->addContextItem('required', 'hydra:required');
+        $link->addContextItem('description', 'rdfs:comment');
+        $link->addContextItem('label', 'rdfs:label');
+        $link->addProperty('hydra:title', $instance['label']);
+        $link->addProperty('hydra:description', $instance['description']);
+        //       $link->addProperty('domain', $service_path . '#EntryPoint');
+        //       $link->addProperty('range', $service_class::$label);
+
+        $ops = array();
+        $op = new TripalWebServiceResource($this->base_path);
+
+        $op->setID('_:' . $field_name . '_retrieve');
+        $op->setType('hydra:Operation');
+        $op->addContextItem('method', 'hydra:method');
+        $op->addContextItem('label', 'rdfs:label');
+        $op->addContextItem('description', 'rdfs:comment');
+        $op->addContextItem('expects', array(
+          "@id" => "hydra:expects",
+          "@type" => "@id"
+        ));
+        $op->addContextItem('returns', array(
+          "@id" => "hydra:returns",
+          "@type" => "@id"
+        ));
+        $op->addContextItem('statusCodes', 'hydra:statusCodes');
+        $op->addProperty('method', "GET");
+        $op->addProperty('label', 'Retrieves the ' . $instance['label'] . ' resource.');
+        $op->addProperty('description', $instance['description']);
+        $op->addProperty('expects', NULL);
+        $op->addProperty('returns', $accession);
+        $op->addProperty('statusCodes', array());
+        $ops[] = $op;
+        $link->addContextItem('supportedOperation', 'hydra:supportedOperation');
+        $link->addProperty('supportedOperation', $ops);
+        $proptype = $link;
+      }
+
       $property = array(
-        'type' => $instance['settings']['term_vocabulary'] . ':' . $instance['settings']['term_accession'],
+        'type' => $proptype,
         'title' => $instance['label'],
         'description' => $instance['description'],
         "required" => $instance['required'] ? TRUE : FALSE,