Browse Source

WS working with HydraConsole, still need to add fields of content types

Stephen Ficklin 7 years ago
parent
commit
d370da91d6

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

@@ -135,7 +135,7 @@ function tripal_chado_populate_vocab_RDFS() {
     '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}',
+    'urlprefix' => 'http://www.w3.org/2000/01/rdf-schema#{accession}',
   ));
   tripal_insert_cv(
     'rdfs',

+ 6 - 0
tripal_chado/tripal_chado.install

@@ -1414,6 +1414,12 @@ function tripal_chado_update_7321() {
       'rdf',
       'Resource Description Framework'
     );
+    tripal_insert_db(array(
+      'name' => 'rdfs',
+      'description' => 'Resource Description Framework Schema',
+      'url' => 'https://www.w3.org/TR/rdf-schema/',
+      'urlprefix' => 'http://www.w3.org/2000/01/rdf-schema#{accession}',
+    ));
     tripal_insert_db(array(
       'name' => 'hydra',
       'description' => 'A Vocabulary for Hypermedia-Driven Web APIs',

+ 45 - 18
tripal_ws/includes/TripalWebService.inc

@@ -55,11 +55,11 @@ class TripalWebService {
   protected $base_path;
 
   /**
-   * The list of classes used by this service. For the web service
+   * The list of documented classes used by this service. For the web service
    * to be discoverable all of the entity classes and their collections
    * must be defined.
    */
-  protected $supported_classes;
+  protected $documentation;
 
   // --------------------------------------------------------------------------
   //                             CONSTRUCTORS
@@ -79,9 +79,9 @@ class TripalWebService {
     $this->path = array();
     $this->params = array();
     $this->base_path = $base_path;
-    $this->supported_classes = array();
+    $this->documentation = array();
 
-    $this->addClass(array(
+    $this->addDocClass(array(
       "id" => "http://www.w3.org/ns/hydra/core#Resource",
       "name" => 'resource',
       "title" => "Resource",
@@ -151,13 +151,13 @@ class TripalWebService {
    * are separated by an underscore.  This function identifies the version
    * from the class name and returns it here in a human-readable format.
    *
-   * @param $sanatize
+   * @param $sanitize
    *   Set to TRUE to convert the period to underscore.
    *
    * @return
    *   The version number for this web service.
    */
-  public function getVersion($sanatize = FALSE) {
+  public function getVersion($sanitize = FALSE) {
 
     $class = get_class($this);
     $major_version = '';
@@ -279,8 +279,8 @@ class TripalWebService {
    *   An array of TripalWebServiceResource objects that follow the Hydra
    *   documentation for documenting supported classes.
    */
-  public function getSupportedClasses() {
-    return $this->supported_classes;
+  public function getDocumentation() {
+    return $this->documentation;
   }
 
   /**
@@ -358,36 +358,45 @@ class TripalWebService {
    *      - domain: the @id of the rdfs:domain.
    *      - range:  the @id of the rdfs:range.
    */
-  protected function addClass($details = array(), $ops = array(), $props = array()) {
+  protected function addDocClass($details = array(), $ops = array(), $props = array()) {
     $supported_class = new TripalWebServiceResource($this->getServicePath());
 
     // Add the context which all classes will need
     $supported_class->addContextItem('description', 'rdfs:comment');
+    $supported_class->addContextItem('subClassOf', 'hydra:subClassOf');
+    $supported_class->addContextItem('description', 'rdfs:comment');
+    $supported_class->addContextItem('label', 'rdfs:label');
 
-    // Add in the Class details.
+    // Set the Class ID.
     $class_id = $details['id'];
     $supported_class->setID($class_id);
+
+    // Set the class Type.
     if (array_key_exists('type', $details)) {
       $supported_class->setType($details['type']);
     }
     else {
       $supported_class->setType('hydra:Class');
     }
+
+    // Set title and description.
     $supported_class->addProperty('hydra:title', $details['title']);
     $supported_class->addProperty('hydra:description', array_key_exists('description', $details) ? $details['description'] : NULL);
+
+    // Set the sub class.
     if (array_key_exists('subClassOf', $details)) {
       if ($details['subClassOf']) {
-        $supported_class->addProperty('hydra:subClassOf', $details['subClassOf']);
+        $supported_class->addProperty('subClassOf', $details['subClassOf']);
       }
     }
     else {
-      $supported_class->addProperty('hydra:subClassOf', 'hydra:Resource');
+      $supported_class->addProperty('subClassOf', 'hydra:Resource');
     }
 
     // Now add the supported operations.
     $class_ops = array();
     foreach ($ops as $op => $op_details) {
-      $class_ops[] = $this->generateClassOp($supported_class, $op, $op_details);
+      $class_ops[] = $this->generateDocClassOp($supported_class, $op, $op_details);
     }
     $supported_class->addContextItem('supportedOperation', 'hydra:supportedOperation');
     $supported_class->addProperty('supportedOperation', $class_ops);
@@ -395,18 +404,18 @@ class TripalWebService {
     // Now add in the supported proprerties.
     $class_props = array();
     foreach ($props as $prop) {
-      $class_props[] = $this->generateClassProp($supported_class, $prop);
+      $class_props[] = $this->generateDocClassProp($supported_class, $prop);
     }
     $supported_class->addContextItem('supportedProperty', 'hydra:supportedProperty');
     $supported_class->addProperty('supportedProperty', $class_props);
 
-    $this->supported_classes[] = $supported_class;
+    $this->documentation[] = $supported_class;
   }
 
   /**
    * A helper function for the addClass() function for generating a property.
    */
-  private function generateClassProp($supported_class, $prop) {
+  private function generateDocClassProp($supported_class, $prop) {
     $supported_class->addContextItem('property', array(
       "@id" => "hydra:property",
       "@type" => "@id"
@@ -447,7 +456,7 @@ class TripalWebService {
   /**
    * A helper function for the addClass() function for generating an operation.
    */
-  private function generateClassOp($supported_class, $op, $op_details) {
+  private function generateDocClassOp($supported_class, $op, $op_details) {
 
     if ($op != 'GET' and $op != 'PUT' and $op != 'DELETE' and $op != 'POST') {
       throw new Exception(t('The method, @method, provided to the TripalWebService::addClass function is not an oppropriate operations.', array('@method' => $op)));
@@ -459,7 +468,21 @@ class TripalWebService {
 
     $class_op = new TripalWebServiceResource($this->base_path);
     $class_op->setID($op_details['type']);
-    $class_op->setType('hydra:Operation');
+    switch($op) {
+      case 'GET':
+        $class_op->setType('hydra:Operation');
+        break;
+      case 'POST':
+        $class_op->setType('http://schema.org/AddAction');
+        break;
+      case 'DELETE':
+        $class_op->setType('http://schema.org/DeleteAction');
+        break;
+      case 'PUT':
+        $class_op->setType('http://schema.org/UpdateAction');
+        break;
+    }
+
     $class_op->addContextItem('method', 'hydra:method');
     $class_op->addContextItem('label', 'rdfs:label');
     $class_op->addContextItem('description', 'rdfs:comment');
@@ -472,6 +495,7 @@ class TripalWebService {
       "@type" => "@id"
     ));
     $class_op->addContextItem('statusCodes', 'hydra:statusCodes');
+    $class_op->addContextItem('code', 'hydra:statusCode');
 
     $class_op->addProperty('method', $op);
     $class_op->addProperty('label', array_key_exists('label', $op_details) ? $op_details['label'] : 'Retrieves an instance of this resource');
@@ -485,6 +509,9 @@ class TripalWebService {
         throw new Exception(t('The status code provided to TripalWebService::addClass function is improperly formatted @code.', array('@code' => print_r($code, TRUE))));
       }
     }
+    if (count($status_codes) == 0) {
+      $class_op->addProperty('statusCodes', array());
+    }
     $class_op->addProperty('expects', array_key_exists('expects', $op_details) ? $op_details['expects'] : NULL);
     $class_op->addProperty('returns', array_key_exists('returns', $op_details) ? $op_details['returns'] : ' "http://www.w3.org/2002/07/owl#Nothing",');
 

+ 95 - 27
tripal_ws/includes/TripalWebService/TripalEntityService_v0_1.inc

@@ -30,8 +30,8 @@ class TripalEntityService_v0_1 extends TripalWebService {
     parent::__construct($base_path);
 
     // Add the classes that this resource supports.
-    $this->addBundleClasses();
-    $this->addContentCollectionClass();
+    $this->addDocBundleClasses();
+    $this->addDocContentCollectionClass();
   }
 
   /**
@@ -768,6 +768,11 @@ class TripalEntityService_v0_1 extends TripalWebService {
     $term = entity_load('TripalTerm', array('id' => $bundle->term_id));
     $term = reset($term);
 
+    // The type of collection is provided by our API vocabulary service.
+    $vocab_service = new TripalVocabService_v0_1($this->base_path);
+    $this->resource->addContextItem('vocab', $vocab_service->getServicePath() . '#');
+    $this->resource->setType('vocab:' . urlencode($bundle->label) . 'Collection');
+
     // Convert term to a simple array
     $term = tripal_get_term_details($term->vocab->vocabulary, $term->accession);
 
@@ -901,7 +906,7 @@ class TripalEntityService_v0_1 extends TripalWebService {
       }
       $this->setResourceType($member, $term);
       $this->addResourceProperty($member, $label, $bundle->label);
-      $member->addContextItem('description', 'hydra:description');
+      $member->addContextItem('description', 'rdfs:comment');
       // Get the bundle description. If no description is provided then
       // use the term definition
       $description = tripal_get_bundle_variable('description', $bundle->id);
@@ -917,14 +922,13 @@ class TripalEntityService_v0_1 extends TripalWebService {
     }
   }
 
+
   /**
-   * Adds the content collection class.
+   * Adds the content collection class to the document for this service.
    */
-  private function addContentCollectionClass() {
-
-    $service_path = $this->getServicePath();
+  private function addDocContentCollectionClass() {
     $details = array(
-      'id' => $service_path,
+      'id' => 'vocab:ContentCollection',
       'title' => 'Content Collection',
     );
     $vocab = tripal_get_vocabulary_details('hydra');
@@ -961,15 +965,15 @@ class TripalEntityService_v0_1 extends TripalWebService {
     $operations['GET'] = array(
       'label' => 'Retrieves a collection of content types available on this site.',
       'expects' => NULL,
-      'returns' => $service_path,
+      'returns' => $this->getServicePath(),
       'type' => '_:content_collection_retrieve'
     );
-    $this->addClass($details,$operations, $propeties);
+    $this->addDocClass($details,$operations, $propeties);
   }
   /**
-   * Adds classes for every content type.
+   * Adds classes for every content type to the documentation for this service.
    */
-  private function addBundleClasses() {
+  private function addDocBundleClasses() {
 
     global $user;
 
@@ -1016,20 +1020,6 @@ class TripalEntityService_v0_1 extends TripalWebService {
         );
       }
 
-      // If the user can create this content type.
-      if (user_access('create ' . $bundle->name)) {
-        $label = "Creates a " . $bundle->label . " entity.";
-        if (preg_match('/^[aeiou]/i', $bundle->label)) {
-          $label = "Creates an " . $bundle->label . " entity.";
-        }
-        $operations['POST'] = array(
-          'label' => $label,
-          'description' => NULL,
-          'returns' => $class_id,
-          'type' => '_:' . preg_replace('/[^\w]/', '_', strtolower($bundle->label)) . '_create',
-        );
-      }
-
       // If the user can edit this content type.
       if (user_access('edit ' . $bundle->name)) {
         $label = "Update and replace a " . $bundle->label . " entity.";
@@ -1059,7 +1049,85 @@ class TripalEntityService_v0_1 extends TripalWebService {
       }
       $properties = array();
 
-      $this->addClass($details, $operations, $properties);
+      $this->addDocClass($details, $operations, $properties);
+
+      // Now add the bundle collection class
+      $this->addDocBundleCollectionClass($bundle);
     } // end while ($bundle = $bundles->fetchObject()) { ...
   }
+
+  /**
+   * Every content type (bundle) needs a collection class in the documentation.
+   */
+  private function addDocBundleCollectionClass($bundle) {
+    $details = array(
+      'id' => 'vocab:' . urlencode($bundle->label) . 'Collection',
+      'title' => $bundle->label . ' Collection',
+      'subClassOf' => 'hydra:Collection',
+      'description' => 'A collection (or list) of ' . $bundle->label . ' resources.',
+    );
+    $vocab = tripal_get_vocabulary_details('hydra');
+    $url = preg_replace('/{accession}/', 'member', $vocab['urlprefix']);
+    $propeties = array();
+    $propeties[] = array(
+      'type' => $url,
+      'title' => 'member',
+      'description' => "The list of available " . $bundle->label . '(s).',
+      "required" => null,
+      "readonly" => FALSE,
+      "writeonly" => FALSE,
+    );
+    $url = preg_replace('/{accession}/', 'totalItems', $vocab['urlprefix']);
+    $propeties[] = array(
+      "type" => $url,
+      "title" => "totalItems",
+      "description" => "The total number of resources.",
+      "required" => null,
+      "readonly" => FALSE,
+      "writeonly" => FALSE
+    );
+    $url = preg_replace('/{accession}/', 'label', $vocab['urlprefix']);
+    $propeties[] = array(
+      "type" => $url,
+      "title" => "label",
+      "description" => "A label or name for the resource.",
+      "required" => null,
+      "readonly" => FALSE,
+      "writeonly" => FALSE
+    );
+
+    $class_id = $this->getServicePath() . '/' . urlencode($bundle->label);
+    $operations = array();
+    $operations['GET'] = array(
+      'label' => 'Retrieves a list of all ' . $bundle->label . ' resources.',
+      'description' => NULL,
+      'expects' => NULL,
+      'returns' => $class_id,
+      'type' => '_:' . preg_replace('/[^\w]/', '_', strtolower($bundle->label)) . '_retrieve',
+    );
+
+    // If the user can create this content type then we allow a POST on the
+    // collection type.
+    if (user_access('create ' . $bundle->name)) {
+      $label = "Creates a " . $bundle->label;
+      if (preg_match('/^[aeiou]/i', $bundle->label)) {
+        $label = "Creates an " . $bundle->label;
+      }
+      $operations['POST'] = array(
+        'label' => $label,
+        'description' => NULL,
+        'expects' => $class_id,
+        'returns' => $class_id,
+        'type' => '_:' . preg_replace('/[^\w]/', '_', strtolower($bundle->label)) . '_create',
+        'statusCodes' => array(
+          array(
+            "code" => 201,
+            "description" => "If the " . $bundle->label . " was created successfully."
+          ),
+        ),
+      );
+    }
+    $this->addDocClass($details, $operations, $propeties);
+  }
+
 }

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

@@ -56,14 +56,14 @@ class TripalVocabService_v0_1 extends TripalWebService {
 
     // Add the EntryPoint class.
     $this->addEntryPointClass();
-    foreach ($this->supported_classes as $supported) {
+    foreach ($this->documentation as $supported) {
       $this->resource->addProperty('supportedClass', $supported);
     }
 
     // Iterate through all of the web services and build their documentation
     foreach ($this->services as $service_class) {
       $service = new $service_class($this->base_path);
-      $supported_classes = $service->getSupportedClasses();
+      $supported_classes = $service->getDocumentation();
       foreach ($supported_classes as $supported) {
         $this->resource->addProperty('supportedClass', $supported);
       }
@@ -106,6 +106,8 @@ class TripalVocabService_v0_1 extends TripalWebService {
       $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', $service_class::$label);
       $link->addProperty('hydra:description', $service_class::$description);
 //       $link->addProperty('domain', $service_path . '#EntryPoint');
@@ -158,6 +160,6 @@ class TripalVocabService_v0_1 extends TripalWebService {
     );
 
 
-    $this->addClass($details, $operations, $properties);
+    $this->addDocClass($details, $operations, $properties);
   }
 }

+ 0 - 1
tripal_ws/tripal_ws.module

@@ -176,7 +176,6 @@ function tripal_ws_get_services() {
     if (!$service) {
       throw new Exception('The service type, "' . $service_type . '", is not available');
     }
-
     // Adjust the path to remove the service type and the version.
     $adj_path = $ws_path;
     array_shift($adj_path);