Browse Source

Fixed lots of bugs with web services and added new update function for tripal_chado

Stephen Ficklin 7 years ago
parent
commit
cab8852f14

+ 0 - 1
tripal/api/tripal.fields.api.inc

@@ -43,7 +43,6 @@ function hook_bundle_fields_info_alter(&$info, $bundle, $term) {
 function hook_bundle_instances_info_alter(&$info, $bundle, $term) {
 function hook_bundle_instances_info_alter(&$info, $bundle, $term) {
 
 
 }
 }
-
 /**
 /**
  * Retrieves a list of TripalField types.
  * Retrieves a list of TripalField types.
  *
  *

+ 54 - 7
tripal/api/tripal.terms.api.inc

@@ -116,7 +116,26 @@ function hook_vocab_get_term($vocabulary, $accession) {
   // See the tripal_chado_vocab_get_term() function for an example.
   // See the tripal_chado_vocab_get_term() function for an example.
 
 
 }
 }
-
+/**
+ * Hook used by the default term storage backend to provide details for a vocab.
+ *
+ * This hook is called by the tripal_entity module to retrieve information
+ * about the vocabulary 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.
+ *
+ * @return
+ *   An array with at least the following keys:
+ *     - name : The full name of the vocabulary.
+ *     - short_name : The short name abbreviation for the vocabulary.
+ *     - description : A brief description of the vocabulary.
+ *     - url : (optional) A URL for the online resources for the vocabulary.
+ */
+function hook_vocab_get_vocabulary($vocabulary) {
+  // See the tripal_chado_vocab_get_vocabulary() function for an example.
+}
 /**
 /**
  * Hook used by the default term storage backend to add new terms.
  * Hook used by the default term storage backend to add new terms.
  *
  *
@@ -175,15 +194,10 @@ function tripal_add_term($details) {
   }
   }
 }
 }
 
 
+
 /**
 /**
  * Retrieves full information about a vocabulary term.
  * 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
  * @param $vocabulary
  *   The vocabulary of the vocabulary in which the term is found.
  *   The vocabulary of the vocabulary in which the term is found.
  * @param $accession
  * @param $accession
@@ -217,3 +231,36 @@ function tripal_get_term_details($vocabulary, $accession) {
     }
     }
   }
   }
 }
 }
+/**
+ * Retrieves full information about a vocabulary.
+ *
+ * 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.
+ *
+ * @return
+ *   An array with at least the following keys:
+ *     - name : The full name of the vocabulary.
+ *     - short_name : The short name abbreviation for the vocabulary.
+ *     - description : A brief description of the vocabulary.
+ *     - url : (optional) A URL for the online resources for the vocabulary.
+ */
+function tripal_get_vocabulary_details($vocabulary) {
+  // 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_vocabulary';
+    if (function_exists($function)) {
+      return $function($vocabulary);
+    }
+  }
+}

+ 55 - 0
tripal/includes/tripal.term_lookup.inc

@@ -25,6 +25,61 @@ function tripal_vocabulary_lookup_form_submit($form, $form_state) {
 
 
 }
 }
 
 
+function tripal_vocabulary_lookup_page($vocabulary) {
+
+  $vocab = tripal_get_vocabulary_details($vocabulary);
+
+  // If we can't find the term then just return a message.
+  if (!$vocab) {
+    drupal_set_message('The vocabulary cannot be found on this site', 'error');
+    return '';
+  }
+
+  $headers = array();
+  $rows = array();
+  $vocab_name = $vocab['name'];
+  if ($vocab['url']) {
+    $vocab_name = l($vocab['name'], $vocab['url'], array('attributes' => array('target' => '_blank')));
+  }
+  $short_name = $vocab['short_name'];
+  $vocab_desc = $vocab['description'];
+  $rows[] = array(
+    array(
+      'data' => 'Name',
+      'header' => TRUE,
+      'width' => '20%',
+    ),
+    $vocab_name,
+  );
+  $rows[] = array(
+    array(
+      'data' => 'Short Name',
+      'header' => TRUE,
+      'width' => '20%',
+    ),
+    $short_name,
+  );
+  $rows[] = array(
+    array(
+      'data' => 'Description',
+      'header' => TRUE,
+      'width' => '20%',
+    ),
+    $vocab_desc,
+  );
+
+  $table = array(
+    'header' => $headers,
+    'rows' => $rows,
+    'attributes' => array(),
+    'sticky' => FALSE,
+    'caption' => 'Vocabulary details',
+    'colgroups' => array(),
+    'empty' => '',
+  );
+  $content =  theme_table($table);
+  return $content;
+}
 /**
 /**
  *
  *
  * @param $vocabulary
  * @param $vocabulary

+ 13 - 13
tripal/tripal.module

@@ -121,17 +121,6 @@ function tripal_menu() {
     'file path' => drupal_get_path('module', 'tripal'),
     'file path' => drupal_get_path('module', 'tripal'),
   );
   );
 
 
-//   $items['admin/tripal/loaders/obo_loader'] = array(
-//     'title' => 'OBO Controlled Vocabulary Loader',
-//     'description' => t("Import vocabularies and terms in OBO format."),
-//     'access arguments' => array('administer tripal'),
-//     'page callback' => 'drupal_get_form',
-//     'page arguments' => array('tripal_vocabulary_import_form'),
-//     'file' => 'includes/tripal.admin.inc',
-//     'file path' => drupal_get_path('module', 'tripal'),
-//     'type' => MENU_NORMAL_ITEM,
-//   );
-
   $items['admin/tripal/extension'] = array(
   $items['admin/tripal/extension'] = array(
     'title' => 'Extensions',
     'title' => 'Extensions',
     'description' => t("Configuration and management pages for Tripal extension modules."),
     'description' => t("Configuration and management pages for Tripal extension modules."),
@@ -286,9 +275,20 @@ function tripal_menu() {
 //     'type' => MENU_NORMAL_ITEM,
 //     'type' => MENU_NORMAL_ITEM,
 //   );
 //   );
 
 
-  $items['cv/lookup/%/%'] = array(
+  $items['cv/lookup/%'] = array(
     'title' => 'Vocabulary Lookup',
     'title' => 'Vocabulary Lookup',
-    'description' => t("Provides a tool to discover controlled vocabularies and their terms used by this site."),
+    'description' => t("Provides a tool to discover controlled vocabularies"),
+    'access arguments' => array('access content'),
+    'page callback' => 'tripal_vocabulary_lookup_page',
+    'page arguments' => array(2),
+    'file' => 'includes/tripal.term_lookup.inc',
+    'file path' => drupal_get_path('module', 'tripal'),
+    'type' => MENU_CALLBACK,
+  );
+
+  $items['cv/lookup/%/%'] = array(
+    'title' => 'Vocabulary Term Lookup',
+    'description' => t("Provides a tool to discover controlled vocabularies terms used by this site."),
     'access arguments' => array('access content'),
     'access arguments' => array('access content'),
     'page callback' => 'tripal_vocabulary_lookup_term_page',
     'page callback' => 'tripal_vocabulary_lookup_term_page',
     'page arguments' => array(2, 3),
     'page arguments' => array(2, 3),

+ 114 - 7
tripal_chado/includes/tripal_chado.semweb.inc

@@ -19,9 +19,11 @@ function tripal_chado_populate_chado_semweb_table() {
   // inserted.
   // inserted.
 
 
   // Now set defaults!
   // Now set defaults!
+  tripal_chado_populate_vocab_DC();
   tripal_chado_populate_vocab_EDAM();
   tripal_chado_populate_vocab_EDAM();
   tripal_chado_populate_vocab_ERO();
   tripal_chado_populate_vocab_ERO();
   tripal_chado_populate_vocab_FOAF();
   tripal_chado_populate_vocab_FOAF();
+  tripal_chado_populate_vocab_HYDRA();
   tripal_chado_populate_vocab_IAO();
   tripal_chado_populate_vocab_IAO();
   tripal_chado_populate_vocab_LOCAL();
   tripal_chado_populate_vocab_LOCAL();
   tripal_chado_populate_vocab_NCBITAXON();
   tripal_chado_populate_vocab_NCBITAXON();
@@ -31,6 +33,7 @@ function tripal_chado_populate_chado_semweb_table() {
   tripal_chado_populate_vocab_SBO();
   tripal_chado_populate_vocab_SBO();
   tripal_chado_populate_vocab_SCHEMA();
   tripal_chado_populate_vocab_SCHEMA();
   tripal_chado_populate_vocab_SIO();
   tripal_chado_populate_vocab_SIO();
+  tripal_chado_populate_vocab_SO();
   tripal_chado_populate_vocab_SWO();
   tripal_chado_populate_vocab_SWO();
   tripal_chado_populate_vocab_TAXRANK();
   tripal_chado_populate_vocab_TAXRANK();
   tripal_chado_populate_vocab_TCONTACT();
   tripal_chado_populate_vocab_TCONTACT();
@@ -55,7 +58,59 @@ function tripal_chado_populate_vocab_FOAF() {
     'Friend of a Friend. A dictionary of people-related terms that can be used in structured data).'
     'Friend of a Friend. A dictionary of people-related terms that can be used in structured data).'
   );
   );
 }
 }
+/**
+ * Adds the Hydra vocabulary
+ */
+function tripal_chado_populate_vocab_HYDRA() {
+
+  tripal_insert_db(array(
+    'name' => 'hydra',
+    'description' => 'A Vocabulary for Hypermedia-Driven Web APIs',
+    'url' => 'https://www.hydra-cg.com/spec/latest/core/',
+    'urlprefix' => 'https://www.hydra-cg.com/spec/latest/core/#{db}:{accession}',
+  ));
+  tripal_insert_cv(
+    'hydra',
+    'A Vocabulary for Hypermedia-Driven Web APIs.'
+  );
 
 
+  $name = tripal_insert_cvterm(array(
+    'id' => 'hydra:Collection',
+    'name' => 'Collection',
+    'cv_name' => 'hydra',
+    'definition' => 'A collection holding references to a number of related resources.',
+  ));
+  $name = tripal_insert_cvterm(array(
+    'id' => 'hydra:member',
+    'name' => 'member',
+    'cv_name' => 'hydra',
+    'definition' => 'A member of the collection',
+  ));
+  $name = tripal_insert_cvterm(array(
+    'id' => 'hydra:description',
+    'name' => 'description',
+    'cv_name' => 'hydra',
+    'definition' => 'A description.',
+  ));
+  $name = tripal_insert_cvterm(array(
+    'id' => 'hydra:totalItems',
+    'name' => 'totalItems',
+    'cv_name' => 'hydra',
+    'definition' => 'The total number of items referenced by a collection.',
+  ));
+  $name = tripal_insert_cvterm(array(
+    'id' => 'hydra:title',
+    'name' => 'title',
+    'cv_name' => 'hydra',
+    'definition' => 'A title, often used along with a description.',
+  ));
+  $name = tripal_insert_cvterm(array(
+    'id' => 'hydra:PartialCollectionView',
+    'name' => 'PartialCollectionView',
+    'cv_name' => 'hydra',
+    'definition' => 'A PartialCollectionView describes a partial view of a Collection. Multiple PartialCollectionViews can be connected with the the next/previous properties to allow a client to retrieve all members of the collection.',
+  ));
+}
 /**
 /**
  * Adds the RDFS database and terms.
  * Adds the RDFS database and terms.
  */
  */
@@ -64,7 +119,7 @@ function tripal_chado_populate_vocab_RDFS() {
     'name' => 'rdfs',
     'name' => 'rdfs',
     'description' => 'Resource Description Framework Schema',
     'description' => 'Resource Description Framework Schema',
     'url' => 'https://www.w3.org/TR/rdf-schema/',
     'url' => 'https://www.w3.org/TR/rdf-schema/',
-    'urlprefix' => 'https://www.w3.org/TR/rdf-schema/#ch_',
+    'urlprefix' => 'https://www.w3.org/TR/rdf-schema/#ch_{accession}',
   ));
   ));
   tripal_insert_cv(
   tripal_insert_cv(
     'rdfs',
     'rdfs',
@@ -99,7 +154,6 @@ function tripal_chado_populate_vocab_SCHEMA() {
     'Schema.org. Schema.org is sponsored by Google, Microsoft, Yahoo and Yandex. The vocabularies are developed by an open community process.'
     'Schema.org. Schema.org is sponsored by Google, Microsoft, Yahoo and Yandex. The vocabularies are developed by an open community process.'
   );
   );
 
 
-
   $term = tripal_insert_cvterm(array(
   $term = tripal_insert_cvterm(array(
     'id' => 'schema:name',
     'id' => 'schema:name',
     'name' => 'name',
     'name' => 'name',
@@ -172,6 +226,13 @@ function tripal_chado_populate_vocab_SCHEMA() {
       tripal_associate_chado_semweb_term($table, 'type_id', $term);
       tripal_associate_chado_semweb_term($table, 'type_id', $term);
     }
     }
   }
   }
+
+  $term = tripal_insert_cvterm(array(
+    'id' => 'schema:ItemPage',
+    'name' => 'ItemPage',
+    'cv_name' => 'schema',
+    'definition' => 'A page devoted to a single item, such as a particular product or hotel.',
+  ));
 }
 }
 
 
 /**
 /**
@@ -217,6 +278,41 @@ function tripal_chado_populate_vocab_SIO() {
   ));
   ));
   tripal_associate_chado_semweb_term('cvterm', 'cv_id', $term);
   tripal_associate_chado_semweb_term('cvterm', 'cv_id', $term);
 }
 }
+
+/**
+ * Adds the details for the SO vocab and db.
+ */
+function tripal_chado_populate_vocab_SO() {
+  tripal_insert_db(array(
+    'name' => 'SO',
+    'description' => 'The sequence ontology.',
+    'url' => 'http://www.sequenceontology.org/',
+    'urlprefix' => 'http://www.sequenceontology.org/browser/current_svn/term/{db}:{accession}',
+  ));
+  tripal_insert_cv('sequence', 'The sequence ontology.');
+}
+
+/**
+ * Adds the DC database.
+ */
+function tripal_chado_populate_vocab_DC() {
+  tripal_insert_db(array(
+    'name' => 'dc',
+    'description' => 'DCMI Metadata Terms.',
+    'url' => 'http://purl.org/dc/dcmitype/',
+    'urlprefix' => 'http://purl.org/dc/terms/{accession}',
+  ));
+  tripal_insert_cv(
+    'dc',
+    'DCMI Metadata Terms.'
+  );
+  $term = tripal_insert_cvterm(array(
+    'id' => 'dc:Service',
+    'name' => 'Service',
+    'cv_name' => 'dc',
+    'definition' => 'A system that provides one or more functions.',
+  ));
+}
 /**
 /**
  * Adds the EDAM database and terms.
  * Adds the EDAM database and terms.
  */
  */
@@ -518,16 +614,19 @@ function tripal_chado_populate_vocab_IAO() {
  * ontology.
  * ontology.
  */
  */
 function tripal_chado_populate_vocab_LOCAL() {
 function tripal_chado_populate_vocab_LOCAL() {
+  global $base_path;
 
 
   tripal_insert_db(array(
   tripal_insert_db(array(
     'name' => 'null',
     'name' => 'null',
-    'description' => 'No online database.'
+    'description' => 'No online database.',
+    'url' => $base_path . 'cv/lookup/null',
+    'urlprefix' => $base_path. 'cv/lookup/{db}/{accession}',
   ));
   ));
   tripal_insert_db(array(
   tripal_insert_db(array(
     'name' => 'local',
     'name' => 'local',
     'description' => 'Terms created for this site.',
     'description' => 'Terms created for this site.',
-    'url' => '/cv/lookup',
-    'urlprefix' => '/cv/lookup/{db}/{accession}',
+    'url' => $base_path . 'cv/lookup/local',
+    'urlprefix' => $base_path . 'cv/lookup/{db}/{accession}',
   ));
   ));
 
 
 
 
@@ -786,7 +885,7 @@ function tripal_chado_populate_vocab_LOCAL() {
   // TODO: these probably have real terms we can use.
   // TODO: these probably have real terms we can use.
 
 
   $term = tripal_insert_cvterm(array(
   $term = tripal_insert_cvterm(array(
-    'id' => 'locak:rank',
+    'id' => 'local:rank',
     'name' => 'rank',
     'name' => 'rank',
     'definition' => 'A taxonmic rank',
     'definition' => 'A taxonmic rank',
     'cv_name' => 'local',
     'cv_name' => 'local',
@@ -1345,7 +1444,7 @@ function tripal_chado_populate_vocab_UO() {
     'url' => 'http://purl.obolibrary.org/obo/uo',
     'url' => 'http://purl.obolibrary.org/obo/uo',
     'urlprefix' => 'http://purl.obolibrary.org/obo/TAXRANK_',
     'urlprefix' => 'http://purl.obolibrary.org/obo/TAXRANK_',
   ));
   ));
-  tripal_insert_cv('uo','Units of Measurement Ontology');
+  tripal_insert_cv('uo', 'Units of Measurement Ontology');
 
 
   $term = tripal_insert_cvterm(array(
   $term = tripal_insert_cvterm(array(
     'id' => 'UO:0000000',
     'id' => 'UO:0000000',
@@ -1361,6 +1460,14 @@ function tripal_chado_populate_vocab_UO() {
  */
  */
 function tripal_chado_populate_vocab_TAXRANK() {
 function tripal_chado_populate_vocab_TAXRANK() {
 
 
+  tripal_insert_db(array(
+    'name' => 'TAXRANK',
+    'description' => 'A vocabulary of taxonomic ranks (species, family, phylum, etc)',
+    'url' => 'http://www.obofoundry.org/ontology/taxrank.html',
+    'urlprefix' => 'http://purl.obolibrary.org/obo/{db}_{accession}',
+  ));
+  tripal_insert_cv('taxonomic_rank', 'A vocabulary of taxonomic ranks (species, family, phylum, etc)');
+
   $term = tripal_get_cvterm(array('id' => 'TAXRANK:0000005'));
   $term = tripal_get_cvterm(array('id' => 'TAXRANK:0000005'));
   tripal_associate_chado_semweb_term('organism', 'genus', $term);
   tripal_associate_chado_semweb_term('organism', 'genus', $term);
 
 

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

@@ -15,6 +15,33 @@ function tripal_chado_vocab_storage_info() {
     ),
     ),
   );
   );
 }
 }
+/**
+ * Implements hook_vocab_get_vocabulary().
+ *
+ * This hook is created by the Tripal module and is not a Drupal hook.
+ */
+function tripal_chado_vocab_get_vocabulary($vocabulary) {
+  // It's possible that Chado is not available (i.e. it gets renamed
+  // for copying) but Tripal has already been prepared and the
+  // entities exist.  If this is the case we don't want to run the
+  // commands below.
+  if (!chado_table_exists('cv')) {
+    return FALSE;
+  }
+  $sql = "
+     SELECT DB.name as name, CV.name as short_name, DB.description, DB.url
+     FROM {db} DB
+      INNER JOIN {dbxref} DBX on DBX.db_id = DB.db_id
+      INNER JOIN {cvterm} CVT on CVT.dbxref_id = DBX.dbxref_id
+      INNER JOIN {cv} CV on CV.cv_id = CVT.cv_id
+     WHERE
+      DB.name = :name
+     LIMIT 1 OFFSET 0
+  ";
+  $result = chado_query($sql, array(':name' => $vocabulary));
+  $result = $result->fetchAssoc();
+  return $result;
+}
 
 
 /**
 /**
  * Implements hook_vocab_get_term().
  * Implements hook_vocab_get_term().

+ 122 - 0
tripal_chado/tripal_chado.install

@@ -873,4 +873,126 @@ function tripal_chado_update_7304() {
     $error = $e->getMessage();
     $error = $e->getMessage();
     throw new DrupalUpdateException('Could not perform update: '. $error);
     throw new DrupalUpdateException('Could not perform update: '. $error);
   }
   }
+}
+/**
+ * Adding missing cv/db details and cvterms.
+ */
+function tripal_chado_update_7305() {
+  try {
+    tripal_insert_db(array(
+      'name' => 'rdfs',
+      'description' => 'Resource Description Framework Schema',
+      'url' => 'https://www.w3.org/TR/rdf-schema/',
+      'urlprefix' => 'https://www.w3.org/TR/rdf-schema/#ch_{accession}',
+    ));
+    tripal_insert_cv('rdfs', 'Resource Description Framework Schema');
+    tripal_insert_db(array(
+      'name' => 'SO',
+      'description' => 'The sequence ontology.',
+      'url' => 'http://www.sequenceontology.org/',
+      'urlprefix' => 'http://www.sequenceontology.org/browser/current_svn/term/{db}:{accession}',
+    ));
+    tripal_insert_cv('sequence', 'The sequence ontology.');
+    tripal_insert_db(array(
+      'name' => 'TAXRANK',
+      'description' => 'A vocabulary of taxonomic ranks (species, family, phylum, etc)',
+      'url' => 'http://www.obofoundry.org/ontology/taxrank.html',
+      'urlprefix' => 'http://purl.obolibrary.org/obo/{db}_{accession}',
+    ));
+    tripal_insert_cv('taxonomic_rank', 'A vocabulary of taxonomic ranks (species, family, phylum, etc)');
+    tripal_insert_db(array(
+      'name' => 'hydra',
+      'description' => 'A Vocabulary for Hypermedia-Driven Web APIs',
+      'url' => 'https://www.hydra-cg.com/spec/latest/core/',
+      'urlprefix' => 'https://www.hydra-cg.com/spec/latest/core/#{db}:{accession}',
+    ));
+    tripal_insert_cv(
+      'hydra',
+      'A Vocabulary for Hypermedia-Driven Web APIs.'
+    );
+    tripal_insert_db(array(
+      'name' => 'dc',
+      'description' => 'DCMI Metadata Terms.',
+      'url' => 'http://purl.org/dc/dcmitype/',
+      'urlprefix' => 'http://purl.org/dc/terms/{accession}',
+    ));
+    tripal_insert_cv(
+      'dc',
+      'DCMI Metadata Terms.'
+    );
+    $term = tripal_insert_cvterm(array(
+      'id' => 'dc:Service',
+      'name' => 'Service',
+      'cv_name' => 'dc',
+      'definition' => 'A system that provides one or more functions.',
+    ));
+    $name = tripal_insert_cvterm(array(
+      'id' => 'hydra:Collection',
+      'name' => 'Collection',
+      'cv_name' => 'hydra',
+      'definition' => 'A collection holding references to a number of related resources.',
+    ));
+    $name = tripal_insert_cvterm(array(
+      'id' => 'hydra:member',
+      'name' => 'member',
+      'cv_name' => 'hydra',
+      'definition' => 'A member of the collection',
+    ));
+    $name = tripal_insert_cvterm(array(
+      'id' => 'hydra:description',
+      'name' => 'description',
+      'cv_name' => 'hydra',
+      'definition' => 'A description.',
+    ));
+    $name = tripal_insert_cvterm(array(
+      'id' => 'hydra:totalItems',
+      'name' => 'totalItems',
+      'cv_name' => 'hydra',
+      'definition' => 'The total number of items referenced by a collection.',
+    ));
+    $name = tripal_insert_cvterm(array(
+      'id' => 'hydra:title',
+      'name' => 'title',
+      'cv_name' => 'hydra',
+      'definition' => 'A title, often used along with a description.',
+    ));
+    $name = tripal_insert_cvterm(array(
+      'id' => 'hydra:PartialCollectionView',
+      'name' => 'PartialCollectionView',
+      'cv_name' => 'hydra',
+      'definition' => 'A PartialCollectionView describes a partial view of a Collection. Multiple PartialCollectionViews can be connected with the the next/previous properties to allow a client to retrieve all members of the collection.',
+    ));
+    $term = tripal_insert_cvterm(array(
+      'id' => 'schema:ItemPage',
+      'name' => 'ItemPage',
+      'cv_name' => 'schema',
+      'definition' => 'A page devoted to a single item, such as a particular product or hotel.',
+    ));
+    global $base_path;
+
+    tripal_insert_db(array(
+      'name' => 'null',
+      'description' => 'No online database.',
+      'url' => $base_path . 'cv/lookup/null',
+      'urlprefix' => $base_path. 'cv/lookup/{db}/{accession}',
+    ));
+    tripal_insert_db(array(
+      'name' => 'local',
+      'description' => 'Terms created for this site.',
+      'url' => $base_path . 'cv/lookup/local',
+      'urlprefix' => $base_path . 'cv/lookup/{db}/{accession}',
+    ));
+    $term = tripal_insert_cvterm(array(
+      'id' => 'local:rank',
+      'name' => 'rank',
+      'definition' => 'A taxonmic rank',
+      'cv_name' => 'local',
+    ));
+
+  }
+  catch (\PDOException $e) {
+    $transaction->rollback();
+    $error = $e->getMessage();
+    throw new DrupalUpdateException('Could not perform update: '. $error);
+  }
 }
 }

+ 2 - 1
tripal_ws/includes/TripalWebService.inc

@@ -250,7 +250,8 @@ class TripalWebService {
    *   The error message to report.
    *   The error message to report.
    */
    */
   public function setError($message) {
   public function setError($message) {
-    $this->resource = new TripalWebServiceResource();
+    $this->resource = new TripalWebServiceResource($this->base_path);
+    $this->resource->setID('error');
     $this->resource->addContextItem('error', 'rdfs:error');
     $this->resource->addContextItem('error', 'rdfs:error');
     $this->resource->addProperty('error', $message);
     $this->resource->addProperty('error', $message);
   }
   }

+ 84 - 73
tripal_ws/includes/TripalWebService/TripalEntityService_v0_1.inc

@@ -91,7 +91,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
     field_attach_load($entity->type, array($entity->id => $entity),
     field_attach_load($entity->type, array($entity->id => $entity),
         FIELD_LOAD_CURRENT, array('field_id' => $field['id']));
         FIELD_LOAD_CURRENT, array('field_id' => $field['id']));
 
 
-    $this->addEntityField($key_adj, $entity, $field, $instance, $service_path, $expfield);
+    $this->addEntityField($key_adj, $term, $entity, $bundle, $field, $instance, $service_path, $expfield);
   }
   }
 
 
   /**
   /**
@@ -127,19 +127,20 @@ class TripalEntityService_v0_1 extends TripalWebService {
     $vocab = $term->vocab;
     $vocab = $term->vocab;
 
 
     // Add the vocabulary to the context.
     // Add the vocabulary to the context.
-    $this->resource->addContextItem($vocab->vocabulary, $term->urlprefix);
     $this->resource->addContextItem($term->name, $term->url);
     $this->resource->addContextItem($term->name, $term->url);
 
 
     // Get the TripalEntity
     // Get the TripalEntity
     $entity = tripal_load_entity('TripalEntity', array('id' => $entity_id));
     $entity = tripal_load_entity('TripalEntity', array('id' => $entity_id));
     $entity = reset($entity);
     $entity = reset($entity);
 
 
+    $itemPage = tripal_get_term_details('schema', 'ItemPage');
+    $label = tripal_get_term_details('rdfs', 'label');
     $this->resource->setID($entity_id);
     $this->resource->setID($entity_id);
     $this->resource->setType($term->name);
     $this->resource->setType($term->name);
-    $this->resource->addContextItem('label', 'rdfs:label');
-    $this->resource->addContextItem('itemPage', 'schema:itemPage');
+    $this->resource->addContextItem('label', $label['url']);
+    $this->resource->addContextItem('ItemPage', $itemPage['url']);
     $this->resource->addProperty('label', $entity->title);
     $this->resource->addProperty('label', $entity->title);
-    $this->resource->addProperty('itemPage', url('/bio_data/' . $entity->id, array('absolute' => TRUE)));
+    $this->resource->addProperty('ItemPage', url('/bio_data/' . $entity->id, array('absolute' => TRUE)));
 
 
     $this->addEntityFields($entity, $bundle, $term, $service_path);
     $this->addEntityFields($entity, $bundle, $term, $service_path);
 
 
@@ -152,6 +153,10 @@ class TripalEntityService_v0_1 extends TripalWebService {
    */
    */
   private function addEntityFields($entity, $bundle, $term, $service_path) {
   private function addEntityFields($entity, $bundle, $term, $service_path) {
 
 
+    // If the entity is set to hide fields that have no values then we
+    // want to honor that in the web services too.
+    $hide_fields = tripal_get_bundle_variable('hide_empty_field', $bundle->id, 'hide');
+
     // Get information about the fields attached to this bundle and sort them
     // Get information about the fields attached to this bundle and sort them
     // in the order they were set for the display.
     // in the order they were set for the display.
     $instances = field_info_instances('TripalEntity', $bundle->name);
     $instances = field_info_instances('TripalEntity', $bundle->name);
@@ -185,56 +190,49 @@ class TripalEntityService_v0_1 extends TripalWebService {
       $vocabulary = $instance['settings']['term_vocabulary'];
       $vocabulary = $instance['settings']['term_vocabulary'];
       $accession = $instance['settings']['term_accession'];
       $accession = $instance['settings']['term_accession'];
       $term = tripal_get_term_details($vocabulary, $accession);
       $term = tripal_get_term_details($vocabulary, $accession);
-      if ($term) {
-        $key = $term['name'];
-        $key_adj = strtolower(preg_replace('/ /', '_', $key));
-        // The term schema:url also points to a recource so we need
-        // to make sure we set the type to be '@id'.
-        if ($vocabulary == 'schema' and $accession == 'url') {
-          $this->resource->addContextItem($key_adj, array(
-            '@id' => $term['url'],
-            '@type' => '@id',
-          ));
-        }
-        else {
-          $this->resource->addContextItem($key_adj, $term['url']);
-        }
-      }
-      else {
+      if (!$term) {
         continue;
         continue;
       }
       }
+      $key = $term['name'];
+      $key_adj = strtolower(preg_replace('/ /', '_', $key));
 
 
       // If this field should not be attached by default then just add a link
       // If this field should not be attached by default then just add a link
       // so that the caller can get the information separately.
       // so that the caller can get the information separately.
       $instance_settings = $instance['settings'];
       $instance_settings = $instance['settings'];
       if (array_key_exists('auto_attach', $instance['settings']) and
       if (array_key_exists('auto_attach', $instance['settings']) and
           $instance_settings['auto_attach'] == FALSE) {
           $instance_settings['auto_attach'] == FALSE) {
-        $this->resource->addContextItem($key_adj, array(
-          '@id' => '', //$response['@context'][$key_adj],
-          '@type' => '@id'
-        ));
         // Add a URL only if there are values. If there are no values then
         // Add a URL only if there are values. If there are no values then
         // don't add a URL which would make the end-user think they can get
         // don't add a URL which would make the end-user think they can get
         // that information.
         // that information.
         $items = field_get_items('TripalEntity', $entity, $field_name);
         $items = field_get_items('TripalEntity', $entity, $field_name);
         if ($items and count($items) > 0 and $items[0]['value']) {
         if ($items and count($items) > 0 and $items[0]['value']) {
-          $this->resource->addProperty($key_adj, $service_path . '/' . $entity->id . '/' . urlencode($key));
+          $this->resource->addContextItem($key_adj, $term['url']);
+          $this->resource->addProperty($key_adj, $service_path . '/' . $entity->id . '/' . urlencode($term['name']));
         }
         }
         else {
         else {
-          $this->resource->addProperty($key_adj, NULL);
+          if ($hide_fields == 'show') {
+            $this->resource->addContextItem($key_adj, $term['url']);
+            $this->resource->addProperty($key_adj, NULL);
+          }
         }
         }
         continue;
         continue;
       }
       }
 
 
       // Get the details for this field for the JSON-LD response.
       // Get the details for this field for the JSON-LD response.
-      $this->addEntityField($key_adj, $entity, $field, $instance, $service_path);
+      $this->addEntityField($key_adj, $term, $entity, $bundle, $field, $instance, $service_path);
     }
     }
   }
   }
 
 
   /**
   /**
    * Adds the field as a property of the entity resource.
    * Adds the field as a property of the entity resource.
    */
    */
-  private function addEntityField($key, $entity, $field, $instance, $service_path, $expfield = NULL) {
+  private function addEntityField($key, $term, $entity, $bundle, $field, $instance,
+      $service_path, $expfield = NULL) {
+
+    // If the entity is set to hide fields that have no values then we
+    // want to honor that in the web services too.
+    $hide_fields = tripal_get_bundle_variable('hide_empty_field', $bundle->id, 'hide');
+
     // Get the field  settings.
     // Get the field  settings.
     $field_name = $field['field_name'];
     $field_name = $field['field_name'];
     $field_settings = $field['settings'];
     $field_settings = $field['settings'];
@@ -252,11 +250,16 @@ class TripalEntityService_v0_1 extends TripalWebService {
 
 
     $values = array();
     $values = array();
     for ($i = 0; $i < count($items); $i++) {
     for ($i = 0; $i < count($items); $i++) {
-      $values[$i] = $this->sanitizeFieldKeys($items[$i]['value'], $service_path);
+      $values[$i] = $this->sanitizeFieldKeys($items[$i]['value'], $bundle, $service_path);
+    }
+
+    if ($hide_fields == 'hide' and empty($values[0])) {
+      return;
     }
     }
 
 
     // If the field cardinality is 1
     // If the field cardinality is 1
-    if ($field[cardinality] == 1) {
+    if ($field['cardinality'] == 1) {
+
       // If the value is an array and this is the field page then all of those
       // If the value is an array and this is the field page then all of those
       // key/value pairs should be added directly to the response.
       // key/value pairs should be added directly to the response.
       if (is_array($values[0])) {
       if (is_array($values[0])) {
@@ -266,41 +269,46 @@ class TripalEntityService_v0_1 extends TripalWebService {
           }
           }
         }
         }
         else {
         else {
+          $this->resource->addContextItem($key, $term['url']);
           $this->resource->addProperty($key, $values[0]);
           $this->resource->addProperty($key, $values[0]);
         }
         }
       }
       }
       // If the value is not an array it's a scalar so add it as is to the
       // If the value is not an array it's a scalar so add it as is to the
       // response.
       // response.
       else {
       else {
+        $this->resource->addContextItem($key, $term['url']);
         $this->resource->addProperty($key, $values[0]);
         $this->resource->addProperty($key, $values[0]);
       }
       }
     }
     }
 
 
     // If the field cardinality is > 1
     // If the field cardinality is > 1
-    if ($field[cardinality] != 1) {
+    if ($field['cardinality'] != 1) {
 
 
       // If this is the expanded field page then we need to swap out
       // If this is the expanded field page then we need to swap out
       // the resource for a collection.
       // the resource for a collection.
-      if ($expfield) {
-        $this->resource = new TripalWebServiceCollection($service_path . '/' . urlencode($expfield));
-        $this->resource->addContextItem('label', 'rdfs:label');
-        $this->resource->addProperty('label', $instance['label']);
-        foreach ($values as $delta => $element) {
-          $member = new TripalWebServiceResource($service_path);
-          foreach ($element as $key => $value) {
-            $member->addContextItem($key, '');
-            $member->addProperty($key, $value);
-          }
-          $this->resource->addMember($member);
+      $response = new TripalWebServiceCollection($service_path . '/' . urlencode($expfield));
+      $label = tripal_get_term_details('rdfs', 'label');
+      $response->addContextItem('label', $label['url']);
+      $response->addProperty('label', $instance['label']);
+      $i = 0;
+      foreach ($values as $delta => $element) {
+        $member = new TripalWebServiceResource($service_path . '/' . urlencode($expfield));
+        $member->setID($i);
+        // Add the context of the parent resource because all of the keys
+        // were santizied and set to match the proper context.
+        $member->setContext($this->resource);
+        $member->setType($key);
+        foreach ($element as $key => $value) {
+          $member->addProperty($key, $value);
         }
         }
+        $response->addMember($member);
+        $i++;
+      }
+      if ($expfield) {
+        $this->resource = $response;
       }
       }
       else {
       else {
-        $response[$key] = array(
-          '@type' => 'Collection',
-          'totalItems' => count($values),
-          'label' => $instance['label'],
-          'member' => $values,
-        );
+        $this->resource->addProperty($key, $response);
       }
       }
     }
     }
   }
   }
@@ -308,7 +316,10 @@ class TripalEntityService_v0_1 extends TripalWebService {
   /**
   /**
    * Rewrites the keys of a field's items array for use with web services.
    * Rewrites the keys of a field's items array for use with web services.
    */
    */
-  private function sanitizeFieldKeys($value, $service_path) {
+  private function sanitizeFieldKeys($value, $bundle, $service_path) {
+    // If the entity is set to hide fields that have no values then we
+    // want to honor that in the web services too.
+    $hide_fields = tripal_get_bundle_variable('hide_empty_field', $bundle->id, 'hide');
 
 
     $new_value = '';
     $new_value = '';
     // If the value is an array rather than a scalar then map the sub elements
     // If the value is an array rather than a scalar then map the sub elements
@@ -316,32 +327,29 @@ class TripalEntityService_v0_1 extends TripalWebService {
     if (is_array($value)) {
     if (is_array($value)) {
       $temp = array();
       $temp = array();
       foreach ($value as $k => $v) {
       foreach ($value as $k => $v) {
+        // exclude fields that have no values so we can hide them
+        if (empty($v) and $hide_fields == 'hide') {
+          continue;
+        }
         $matches = array();
         $matches = array();
         if (preg_match('/^(.+):(.+)$/', $k, $matches)) {
         if (preg_match('/^(.+):(.+)$/', $k, $matches)) {
           $vocabulary = $matches[1];
           $vocabulary = $matches[1];
           $accession = $matches[2];
           $accession = $matches[2];
           $term = tripal_get_term_details($vocabulary, $accession);
           $term = tripal_get_term_details($vocabulary, $accession);
+
           $key_adj = strtolower(preg_replace('/ /', '_', $term['name']));
           $key_adj = strtolower(preg_replace('/ /', '_', $term['name']));
           if (is_array($v)) {
           if (is_array($v)) {
-            $temp[$key_adj] = $this->sanitizeFieldKeys($v, $service_path);
+            $temp[$key_adj] = $this->sanitizeFieldKeys($v, $bundle, $service_path);
           }
           }
           else {
           else {
             $temp[$key_adj] = $v !== "" ? $v : NULL;
             $temp[$key_adj] = $v !== "" ? $v : NULL;
           }
           }
-          // The term schema:url also points to a recource so we need
-          // to make sure we set the type to be '@id'.
-          if ($vocabulary == 'schema' and $accession == 'url') {
-            $this->resource->addContextItem($key_adj, array(
-              '@id' => $term['url'],
-              '@type' => '@id',
-            ));
-          }
-          else {
-            $this->resource->addContextItem($key_adj, $term['url']);
-          }
+          $this->resource->addContextItem($key_adj, $term['url']);
+
         }
         }
         else {
         else {
-          $temp[$k] = $v;
+          // TODO: this is an error, if we get here then we have
+          // a key that isn't using the proper format... what to do?
         }
         }
       }
       }
       $new_value = $temp;
       $new_value = $temp;
@@ -368,7 +376,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
     }
     }
     foreach ($items as $key => $value) {
     foreach ($items as $key => $value) {
       if (is_array($value)) {
       if (is_array($value)) {
-        $this->sanitizeFieldEntity($items[$key], $response, $api_url);
+        $this->sanitizeFieldEntity($items[$key], $service_path);
         continue;
         continue;
       }
       }
 
 
@@ -378,7 +386,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
           $item_entity = tripal_load_entity($item_etype, array($item_eid));
           $item_entity = tripal_load_entity($item_etype, array($item_eid));
           $item_entity = reset($item_entity);
           $item_entity = reset($item_entity);
           $bundle = tripal_load_bundle_entity(array('name' => $item_entity->bundle));
           $bundle = tripal_load_bundle_entity(array('name' => $item_entity->bundle));
-          $items['@id'] = url($api_url . '/content/' . $bundle->label . '/' . $item_eid, array('absolute' => TRUE));
+          $items['@id'] = $this->getServicePath() . '/' . urlencode($bundle->label) . '/' . $item_eid;
         }
         }
         unset($items['entity']);
         unset($items['entity']);
       }
       }
@@ -390,8 +398,9 @@ class TripalEntityService_v0_1 extends TripalWebService {
    */
    */
   private function doContentTypeList($ctype) {
   private function doContentTypeList($ctype) {
     $service_path = $this->getServicePath() . '/' . urlencode($ctype);
     $service_path = $this->getServicePath() . '/' . urlencode($ctype);
+    $label = tripal_get_term_details('rdfs', 'label');
     $this->resource = new TripalWebServiceCollection($service_path);
     $this->resource = new TripalWebServiceCollection($service_path);
-    $this->resource->addContextItem('label', 'rdfs:label');
+    $this->resource->addContextItem('label', $label['url']);
 
 
     // Get the TripalBundle, TripalTerm and TripalVocab type for this type.
     // Get the TripalBundle, TripalTerm and TripalVocab type for this type.
     $bundle = tripal_load_bundle_entity(array('label' => $ctype));
     $bundle = tripal_load_bundle_entity(array('label' => $ctype));
@@ -567,8 +576,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
     // Now perform the query.
     // Now perform the query.
     $results = $query->execute();
     $results = $query->execute();
 
 
-    //$this->resource->initPager($num_records, $params['limit']);
-    $this->resource->initPager($num_records, $limit);
+    $this->resource->initPager($num_records, $limit, $page);
 
 
     // Iterate through the entities and add them to the list.
     // Iterate through the entities and add them to the list.
     foreach ($results['TripalEntity'] as $entity_id => $stub) {
     foreach ($results['TripalEntity'] as $entity_id => $stub) {
@@ -582,14 +590,16 @@ class TripalEntityService_v0_1 extends TripalWebService {
       $query->condition('TE.id', $entity_id);
       $query->condition('TE.id', $entity_id);
       $entity = $query->execute()->fetchObject();
       $entity = $query->execute()->fetchObject();
 
 
+      $itemPage = tripal_get_term_details('schema', 'ItemPage');
+      $label = tripal_get_term_details('rdfs', 'label');
       $member = new TripalWebServiceResource($service_path);
       $member = new TripalWebServiceResource($service_path);
-      $member->addContextItem('label', 'rdfs:label');
-      $member->addContextItem('itemPage', 'schema:itemPage');
+      $member->addContextItem('label', $label['url']);
+      $member->addContextItem('ItemPage', $itemPage['url']);
       $member->addContextItem($term->name, $term->url);
       $member->addContextItem($term->name, $term->url);
       $member->setID($entity->id);
       $member->setID($entity->id);
       $member->setType($term->name);
       $member->setType($term->name);
       $member->addProperty('label', $entity->title);
       $member->addProperty('label', $entity->title);
-      $member->addProperty('itemPage', url('/bio_data/' . $entity->id, array('absolute' => TRUE)));
+      $member->addProperty('ItemPage', url('/bio_data/' . $entity->id, array('absolute' => TRUE)));
       $this->resource->addMember($member);
       $this->resource->addMember($member);
     }
     }
   }
   }
@@ -599,8 +609,9 @@ class TripalEntityService_v0_1 extends TripalWebService {
    */
    */
   private function doAllTypesList() {
   private function doAllTypesList() {
     $service_path = $this->getServicePath();
     $service_path = $this->getServicePath();
+    $label = tripal_get_term_details('rdfs', 'label');
     $this->resource = new TripalWebServiceCollection($service_path);
     $this->resource = new TripalWebServiceCollection($service_path);
-    $this->resource->addContextItem('label', 'rdfs:label');
+    $this->resource->addContextItem('label', $label['url']);
     $this->resource->addProperty('label', 'Content Types');
     $this->resource->addProperty('label', 'Content Types');
 
 
     // Get the list of published terms (these are the bundle IDs)
     // Get the list of published terms (these are the bundle IDs)
@@ -624,7 +635,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
       }
       }
       $member = new TripalWebServiceResource($service_path);
       $member = new TripalWebServiceResource($service_path);
       $member->addContextItem($term->name, $term->url);
       $member->addContextItem($term->name, $term->url);
-      $member->addContextItem('label', 'rdfs:label');
+      $member->addContextItem('label', $label['url']);
       $member->addContextItem('description', 'hydra:description');
       $member->addContextItem('description', 'hydra:description');
       $member->setID(urlencode($bundle->label));
       $member->setID(urlencode($bundle->label));
       $member->setType($term->name);
       $member->setType($term->name);

+ 15 - 7
tripal_ws/includes/TripalWebServiceCollection.inc

@@ -26,6 +26,11 @@ class TripalWebServiceCollection extends TripalWebServiceResource {
    */
    */
   protected $itemsPerPage;
   protected $itemsPerPage;
 
 
+  /**
+   * The current page of the pager.
+   */
+  protected $page;
+
 
 
   /**
   /**
    * Implements the constructor.
    * Implements the constructor.
@@ -36,9 +41,12 @@ class TripalWebServiceCollection extends TripalWebServiceResource {
   public function __construct($service_path) {
   public function __construct($service_path) {
     parent::__construct($service_path);
     parent::__construct($service_path);
     $this->members = array();
     $this->members = array();
-    $this->addContextItem('Collection', "hydra:Collection");
-    $this->addContextItem('totalItems', "hydra:totalItems");
-    $this->addContextItem('member', "member");
+    $term = tripal_get_term_details('hydra', 'Collection');
+    $this->addContextItem('Collection', $term['url']);
+    $term = tripal_get_term_details('hydra', 'totalItems');
+    $this->addContextItem('totalItems', $term['url']);
+    $term = tripal_get_term_details('hydra', 'member');
+    $this->addContextItem('member', $term['url']);
     parent::setType('Collection');
     parent::setType('Collection');
 
 
     // If the totalItems is set to -1 then this means paging is turned off and
     // If the totalItems is set to -1 then this means paging is turned off and
@@ -58,10 +66,11 @@ class TripalWebServiceCollection extends TripalWebServiceResource {
    * @param $path
    * @param $path
    *   The path
    *   The path
    */
    */
-  public function initPager($totalItems, $itemsPerPage, $path) {
+  public function initPager($totalItems, $itemsPerPage, $page) {
     $this->doPaging = TRUE;
     $this->doPaging = TRUE;
     $this->totalItems = $totalItems;
     $this->totalItems = $totalItems;
     $this->itemsPerPage = $itemsPerPage;
     $this->itemsPerPage = $itemsPerPage;
+    $this->page = $page;
   }
   }
 
 
   /**
   /**
@@ -104,7 +113,7 @@ class TripalWebServiceCollection extends TripalWebServiceResource {
 
 
       $data['totalItems'] = $this->totalItems;
       $data['totalItems'] = $this->totalItems;
       $total_pages = ceil($this->totalItems / $this->itemsPerPage);
       $total_pages = ceil($this->totalItems / $this->itemsPerPage);
-      $page = array_key_exists('page', $this->params) ? $this->params['page'] : 1;
+      $page = $this->page;
       $limit = $this->itemsPerPage;
       $limit = $this->itemsPerPage;
 
 
       if ($this->totalItems > 0) {
       if ($this->totalItems > 0) {
@@ -123,10 +132,9 @@ class TripalWebServiceCollection extends TripalWebServiceResource {
           $data['view']['next'] = $this->service_path . '?' . implode('&', array("page=$next", "limit=$limit"));
           $data['view']['next'] = $this->service_path . '?' . implode('&', array("page=$next", "limit=$limit"));
         }
         }
       }
       }
-
     }
     }
     else {
     else {
-      $data['totalItems'] = count($member_data);
+      $data['totalItems'] = count($this->members);
     }
     }
 
 
     $member_data = array();
     $member_data = array();

+ 24 - 4
tripal_ws/includes/TripalWebServiceResource.inc

@@ -42,10 +42,17 @@ class TripalWebServiceResource {
 
 
     // First, add the RDFS and Hydra vocabularies to the context.  All Tripal
     // First, add the RDFS and Hydra vocabularies to the context.  All Tripal
     // web services should use these.
     // web services should use these.
-    $this->addContextItem('rdfs', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
-    $this->addContextItem('hydra', 'http://www.w3.org/ns/hydra/core#');
-    $this->addContextItem('dc', 'http://purl.org/dc/dcmitype/');
-    $this->addContextItem('schema', 'https://schema.org/');
+    $vocab = tripal_get_vocabulary_details('rdfs');
+    $this->addContextItem('rdfs', $vocab['url']);
+
+    $vocab = tripal_get_vocabulary_details('hydra');
+    $this->addContextItem('hydra', $vocab['url']);
+
+    $vocab = tripal_get_vocabulary_details('dc');
+    $this->addContextItem('dc', $vocab['url']);
+
+    $vocab = tripal_get_vocabulary_details('schema');
+    $this->addContextItem('schema', $vocab['url']);
 
 
     $this->data['@id'] = $service_path;
     $this->data['@id'] = $service_path;
     $this->data['@type'] = '';
     $this->data['@type'] = '';
@@ -228,4 +235,17 @@ class TripalWebServiceResource {
       return $this->context;
       return $this->context;
   }
   }
 
 
+  /**
+   * Copies the context from a given TripalWebService resource to this
+   * resource.
+   *
+   * @param $resource
+   */
+  public function setContext($resource) {
+    if (!is_a($resource, 'TripalWebServiceResource')) {
+      throw new Exception("The \$resource argument must be an instance of a TripalWebServiceResource.");
+    }
+    $this->context = $resource->getContext();
+  }
+
 }
 }

+ 1 - 1
tripal_ws/tripal_ws.module

@@ -305,7 +305,7 @@ function tripal_ws_load_remote_entity($site_id, $api_version, $ctype, $id) {
   drupal_set_title($response['label']);
   drupal_set_title($response['label']);
 
 
   // Attribute this data to the proper source.
   // Attribute this data to the proper source.
-  $source_url = l($response['label'], $response['itemPage'], array('attributes' => array('target' => '_blank')));
+  $source_url = l($response['label'], $response['ItemPage'], array('attributes' => array('target' => '_blank')));
   $content = '<div><strong>Source:</strong> ' . $site->name . ': ' . $source_url . '</div>';
   $content = '<div><strong>Source:</strong> ' . $site->name . ': ' . $source_url . '</div>';
 
 
   // Fake an entity so we can display this content using the same
   // Fake an entity so we can display this content using the same