浏览代码

Addded the OBO loader to the tripal_cv module and created an online form for starting OBO parsing jobs

spficklin 14 年之前
父节点
当前提交
355491bdfa
共有 3 个文件被更改,包括 824 次插入88 次删除
  1. 580 0
      tripal_cv/obo_loader.php
  2. 48 0
      tripal_cv/tripal_cv.install
  3. 196 88
      tripal_cv/tripal_cv.module

+ 580 - 0
tripal_cv/obo_loader.php

@@ -0,0 +1,580 @@
+<?php
+
+
+/*************************************************************************
+*
+*/
+function tripal_cv_load_obo_v1_2($file) {
+
+   $header = array();
+   $obo = array();
+   
+   print "Opening File $file\n";
+
+   // set the search path
+   db_query("set search_path to chado,public");  // TODO: fix this
+
+   // make sure we have an 'internal' and a '_global' database
+   if(!tripal_cv_obo_add_db('internal')){
+      return tripal_cv_obo_loader_done();
+   }
+   if(!tripal_cv_obo_add_db('_global')){
+      return tripal_cv_obo_loader_done();
+   }
+
+   // parse the obo file
+   tripal_cv_obo_parse($file,$obo,$header);
+
+   // add the CV for this ontology to the database
+   $cv = tripal_cv_obo_add_cv($header['default-namespace'][0],'');
+   if(!$cv){
+      return tripal_cv_obo_loader_done();
+   }  
+
+   // add any typedefs to the vocabulary first
+   $typedefs = $obo['Typedef'];
+   foreach($typedefs as $typedef){
+      tripal_cv_obo_process_stanza($typedef,$cv,1);  
+   }
+
+   // next add terms to the vocabulary
+   $terms = $obo['Term'];
+   if(!tripal_cv_obo_process_stanza($terms,$cv,$obo)){
+      return tripal_cv_obo_loader_done();   
+   }
+   return tripal_cv_obo_loader_done();
+}
+
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_process_stanza($terms,$cv,$obo,$is_relationship=0){
+
+   foreach ($terms as $term){
+
+      // add the cvterm
+      $cvterm = tripal_cv_obo_add_cv_term($term,$cv,$is_relationship,1);     
+      if(!$cvterm){ return 0; }
+
+      // now handle other properites
+      if(isset($term['is_anonymous'])){
+        print "WARNING: unhandled tag: is_anonymous\n";
+      }
+      if(isset($term['alt_id'])){
+         foreach($term['alt_id'] as $alt_id){
+            if(!tripal_cv_obo_add_cvterm_dbxref($cvterm,$alt_id)){
+               return 0;
+            }
+         }
+      }
+      if(isset($term['subset'])){
+        print "WARNING: unhandled tag: subset\n";
+      }
+      // add synonyms for this cvterm
+      if(isset($term['synonym'])){
+         if(!tripal_cv_obo_add_synonyms($term,$cvterm)){
+            return 0;
+         }
+      }
+      if(isset($term['exact_synonym'])){
+        // depricated
+        print "WARNING: unhandled tag: exact_synonym\n";
+      }
+      if(isset($term['narrow_synonym'])){
+        print "WARNING: unhandled tag: narrow_synonym\n";
+        // depricated
+      }
+      if(isset($term['broad_synonym'])){
+        print "WARNING: unhandled tag: broad_synonym\n";
+        // depricated
+      }
+      // add the comment to the cvtermprop table
+      if(isset($term['comment'])){
+         $comments = $term['comment'];
+         $j = 0;
+         foreach($comments as $comment){
+            if(!tripal_cv_obo_add_cvterm_prop($cvterm,'comment',$comment,$j)){
+               return 0;
+            }
+            $j++;
+         }
+      }    
+      // add any other external dbxrefs
+      if(isset($term['xref']) or isset($term['xref_analog']) or isset($term['xref_unk'])){
+         foreach($term['xref'] as $xref){
+            if(!tripal_cv_obo_add_cvterm_dbxref($cvterm,$xref)){
+               return 0;
+            }
+         }
+      }
+
+      // add is_a relationships for this cvterm
+      if(isset($term['is_a'])){
+         foreach($term['is_a'] as $is_a){
+            if(!tripal_cv_obo_add_relationship($cvterm,$cv,$obo,'is_a',$is_a)){
+               return 0;
+            }
+         }
+      } 
+      if(isset($term['intersection_of'])){
+        print "WARNING: unhandled tag: intersection_of\n";
+      }
+      if(isset($term['union_of'])){
+        print "WARNING: unhandled tag: union_on\n";
+      }
+      if(isset($term['disjoint_from'])){
+        print "WARNING: unhandled tag: disjoint_from\n";
+      }
+      if(isset($term['relationship'])){
+         foreach($term['relationship'] as $value){
+            $rel = preg_replace('/^(.+?)\s.+?$/','\1',$value);
+            $object = preg_replace('/^.+?\s(.+?)$/','\1',$value);
+            if(!tripal_cv_obo_add_relationship($cvterm,$cv,$obo,$rel,$object)){
+               return 0;
+            }
+         }
+      }
+      if(isset($term['replaced_by'])){
+        print "WARNING: unhandled tag: replaced_by\n";
+      }
+      if(isset($term['consider'])){
+        print "WARNING: unhandled tag: consider\n";
+      }
+      if(isset($term['use_term'])){
+        print "WARNING: unhandled tag: user_term\n";
+      }
+      if(isset($term['builtin'])){
+        print "WARNING: unhandled tag: builtin\n";
+      }
+   }   
+   return 1;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_add_db($dbname){
+
+   $db_sql = "SELECT * FROM {db} WHERE name ='%s'";
+   $db = db_fetch_object(db_query($db_sql,$dbname));
+   if(!$db){
+      if(!db_query("INSERT INTO {db} (name) VALUES ('%s')",$dbname)){
+         print "Cannot create '$dbname' db in Chado.";
+         return 0;
+      }      
+     $db = db_fetch_object(db_query($db_sql,$dbname));
+   }
+   return $db;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_add_cv($name,$comment){
+
+ // see if the CV (default-namespace) exists already in the database
+   $vocab = $name;
+   $remark = $comment;
+   $cv_sql = "SELECT * FROM {cv} WHERE name = '%s'";
+   $cv = db_fetch_object(db_query($cv_sql,$vocab));
+
+   // if the CV exists then update it, otherwise insert
+   if(!$cv){
+      $sql = "INSERT INTO {cv} (name,definition) VALUES ('%s','%s')";
+      if(!db_query($sql,$vocab,$remark)){
+         print "Failed to create the CV record";
+         return 0;
+      }
+      $cv = db_fetch_object(db_query($cv_sql,$vocab));
+   } else {
+      $sql = "UPDATE {cv} SET definition = '%s' WHERE name ='%s'";
+      if(!db_query($sql,$remark,$vocab)){
+         print "Failed to update the CV record";
+         return 0;
+      }
+      $cv = db_fetch_object(db_query($cv_sql,$vocab));
+   }
+   return $cv;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_add_cvterm_prop($cvterm,$property,$value,$rank){
+
+   // make sure the 'cvterm_property_type' CV exists
+   $cv = tripal_cv_obo_add_cv($property,'');
+   if(!$cv){ return 0; }
+
+   // get the property type cvterm.  If it doesn't exist then we want to add it
+   $sql = "
+        SELECT * 
+        FROM {cvterm} CVT INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
+        WHERE CVT.name = '%s' and CV.name = '%s'
+   ";
+   $cvproptype = db_fetch_object(db_query($sql,$property,'cvterm_property_type'));
+   if(!$cvproptype){
+      $term = array(
+         'name' => array($property),
+         'id' => array("internal:$property"),
+         'definition' => array(''),
+         'is_obsolete' => array(0),
+      );
+      $cvproptype = tripal_cv_obo_add_cv_term($term,$cv,0,0);
+      if(!$cvproptype){  return 0; }      
+   }
+
+
+   // remove any properties that currently exist for this term.  We'll reset them
+   if($rank == 0){
+      $sql = "DELETE FROM {cvtermprop} WHERE cvterm_id = %d";
+      db_query($sql,$cvterm->cvterm_id);
+   }
+
+   // now add the property
+   $sql = "INSERT INTO {cvtermprop} (cvterm_id,type_id,value,rank) ".
+          "VALUES (%d, %d, '%s',%d)";
+   if(!db_query($sql,$cvterm->cvterm_id,$cvproptype->cvterm_id,$value,$rank)){
+      print "Could not add property $property for term\n";
+      return 0;
+   }
+   return 1;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_add_relationship($cvterm,$cv,$obo,$rel,$objname){
+
+   // make sure the relationship cvterm exists
+   $sql = "
+        SELECT * 
+        FROM {cvterm} CVT INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
+        WHERE CVT.name = '%s' and CV.name = '%s'
+   ";
+   $cvisa = db_fetch_object(db_query($sql,$rel,$cv->name));
+   if(!$cvisa){
+      $term = array(
+         'name' => array($rel),
+         'id' => array($rel),
+         'definition' => array(''),
+         'is_obsolete' => array(0),
+      );
+      if(!tripal_cv_obo_add_cv_term($term,$cv,1,1)){
+         print "Cannot find or insert the relationship term: $rel.\n";
+         return 0;
+      }
+      $cvisa = db_fetch_object(db_query($sql,$rel,$cv->name));
+   }
+
+   // get the object term
+   $objterm = tripal_cv_obo_get_term($obo,$objname);
+   if(!$objterm) { 
+      print "Could not find object term $objname\n";
+      return 0; 
+   }
+   $objcvterm = tripal_cv_obo_add_cv_term($objterm,$cv,1,1);
+   if(!$objcvterm){ return 0; }
+
+   // check to see if the cvterm_relationship already exists, if not add it
+   $cvrsql = "SELECT * FROM {cvterm_relationship} WHERE type_id = %d and subject_id = %d and object_id = %d";
+   if(!db_fetch_object(db_query($cvrsql,$cvisa->cvterm_id,$cvterm->cvterm_id,$objcvterm->cvterm_id))){
+      $sql = "INSERT INTO {cvterm_relationship} ".
+             "(type_id,subject_id,object_id) VALUES (%d,%d,%d)";
+      if(!db_query($sql,$cvisa->cvterm_id,$cvterm->cvterm_id,$objcvterm->cvterm_id)){
+         print "Cannot add $rel relationship";
+         return 0;
+      }
+//      print  "  $rel $objname\n";
+   }
+
+   return 1;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_get_term($obo,$id){
+   foreach ($obo as $type){
+      foreach ($type as $term){
+         $accession = $term['id'][0];
+         if(strcmp($accession,$id)==0){
+            return $term;
+         }
+      }
+   }
+   return;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_add_synonyms($term,$cvterm){
+
+   // make sure we have a 'synonym_type' vocabulary
+   $sql = "SELECT * FROM {cv} WHERE name='synonym_type'";
+   $syncv = db_fetch_object(db_query($sql));
+   if(!$syncv){
+      $sql = "INSERT INTO {cv} (name,definition) VALUES ('synonym_type','')";
+      if(!db_query($sql)){
+         print "Failed to add the synonyms type vocabulary";
+         return 0;
+      }
+   }
+
+   // now add the synonyms
+   if(isset($term['synonym'])){
+      foreach($term['synonym'] as $synonym){
+         // separate out the synonym definition and the synonym type
+         $def = preg_replace('/^\s*"(.*)"\s*.*$/','\1',$synonym);
+         $type = strtolower(preg_replace('/^.*"\s+(.*?)\s+.*$/','\1',$synonym)); 
+
+         // make sure the synonym type exists in the 'synonym_type' vocabulary
+         $cvtsql = "
+            SELECT * 
+            FROM {cvterm} CVT
+               INNER JOIN {cv} CV ON CVT.cv_id = CV.cv_id
+            WHERE CVT.name = '%s' and CV.name = '%s'
+         ";
+         $syntype = db_fetch_object(db_query($cvtsql,$type,'synonym_type'));
+         if(!$syntype){
+            // build a 'term' object so we can add the missing term
+            $term = array(
+               'name' => array($type),
+               'id' => array("internal:$type"),
+               'definition' => array(''),
+               'is_obsolete' => array(0),
+            );
+            if(!tripal_cv_obo_add_cv_term($term,$syncv,0,1)){
+               return 0;
+            }
+            $syntype = db_fetch_object(db_query($cvtsql,$type,'synonym_type'));
+         }       
+
+         // make sure the synonym doesn't already exists
+         $sql = "
+            SELECT * 
+            FROM {cvtermsynonym} 
+            WHERE cvterm_id = %d and synonym = '%s' and type_id = %d
+         ";
+         $syn = db_fetch_object(db_query($sql,$cvterm->cvterm_id,$def,$syntype->cvterm_id));
+         if(!$syn){
+            $sql = "INSERT INTO {cvtermsynonym} (cvterm_id,synonym,type_id)
+                    VALUES(%d,'%s',%d)";
+            if(!db_query($sql,$cvterm->cvterm_id,$def,$syntype->cvterm_id)){
+               print "Failed to insert the synonym for term: $name ($def)\n";
+               return 0;
+            }
+         }            
+      } 
+   }
+   return 1;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_add_cv_term($term,$cv,$is_relationship = 0,$update = 1){
+
+   // get the term properties
+   $id = $term['id'][0];
+   $name = $term['name'][0];
+   $definition = preg_replace('/^\"(.*)\"/','\1',$term['def'][0]);
+   $is_obsolete = 0;
+   if(isset($term['is_obsolete'][0]) and  strcmp($term['is_obsolete'][0],'true')==0){
+     $is_obsolete = 1;
+   }
+
+   // get the accession and the database from the cvterm
+   if(preg_match('/^.+?:.*$/',$id)){
+      $accession = preg_replace('/^.+?:(.*)$/','\1',$id);
+      $dbname = preg_replace('/^(.+?):.*$/','\1',$id);
+   } 
+   else if($is_relationship) {
+      $accession = $id;
+      $dbname = 'OBO_REL';
+   }
+
+   // check to see if the database exists
+   $db = tripal_cv_obo_add_db($dbname);
+   if(!$db){
+      print "Cannot find database '$dbname' in Chado.\n";
+      return 0;
+   }
+
+   // check to see if the cvterm already exists
+   $cvtermsql = "SELECT * from {cvterm} WHERE name = '%s' and cv_id = %d";
+   $cvterm = db_fetch_object(db_query($cvtermsql,$name,$cv->cv_id));
+
+   // if the cvterm doesn't exist then add it otherwise just update it
+   if(!$cvterm){
+      // check to see if the dbxref exists if not, add it
+      $dbxref =  tripal_cv_obo_add_dbxref($db->db_id,$accession);
+      if(!$dbxref){
+         print "Failed to find or insert the dbxref record for cvterm, $name (id: $accession), for database $dbname\n";
+         return 0;
+      }
+
+      // now add the cvterm
+      $sql = "
+         INSERT INTO {cvterm} (cv_id, name, definition, dbxref_id, 
+            is_obsolete, is_relationshiptype) 
+         VALUES (%d,'%s','%s',%d,%d,%d)
+      ";
+      if(!db_query($sql,$cv->cv_id,$name,$definition,
+          $dbxref->dbxref_id,$is_obsolete,$is_relationship)){
+         print "Failed to insert the term: $id\n";
+         return 0;
+      }     
+      print "Added CV term: $id\n";
+      $cvterm = db_fetch_object(db_query($cvtermsql,$name,$cv->cv_id));
+   }
+   elseif($update) { // update the cvterm
+      $sql = "
+         UPDATE {cvterm} SET name='%s', definition='%s',
+            is_obsolete = %d, is_relationshiptype = %d
+         WHERE cvterm_id = %d
+      ";
+      if(!db_query($sql,$term['name'][0],$definition,
+          $is_obsolete,$is_relationship,$cvterm->cvterm_id)){
+         print "Failed to update the term: $name\n";
+         return 0;
+      }  
+      print "Updated CV term: $id\n";
+      $cvterm = db_fetch_object(db_query($cvtermsql,$name,$cv->cv_id));         
+   }
+   // return the cvterm
+   return $cvterm;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_add_cvterm_dbxref($cvterm,$xref){
+
+   $accession = preg_replace('/^.+?:(.*)$/','\1',$xref);
+   $dbname = preg_replace('/^(.+?):.*$/','\1',$xref);
+
+   // if the xref is a database link, handle that specially
+   if(strcmp($dbname,'http')==0){
+      $accession = $xref;
+      $dbname = 'URL';
+   }
+
+   // check to see if the database exists
+   $db = tripal_cv_obo_add_db($dbname);
+   if(!$db){
+      print "Cannot find database '$dbname' in Chado.";
+      return 0;
+   }
+
+   // now add the dbxref
+   $dbxref = tripal_cv_obo_add_dbxref($db->db_id,$accession);
+   if(!$dbxref){ return 0;}
+
+   // finally add the cvterm_dbxref but first check to make sure it exists
+   $sql = "SELECT * from {cvterm_dbxref} WHERE cvterm_id = %d and dbxref_id = %d";
+   if(!db_fetch_object(db_query($sql,$cvterm->cvterm_id,$dbxref->dbxref_id))){            
+      $sql = "INSERT INTO {cvterm_dbxref} (cvterm_id,dbxref_id)".
+             "VALUES (%d,%d)";
+      if(!db_query($sql,$cvterm->cvterm_id,$dbxref->dbxref_id)){
+         print "Cannot add cvterm_dbxref: $accession\n";
+         return 0;
+      }
+   }
+   return 1;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_add_dbxref($db_id,$accession,$version='',$description=''){
+
+   // check to see if the dbxref exists if not, add it
+   $dbxsql = "SELECT dbxref_id FROM {dbxref} WHERE db_id = %d and accession = '%s'";
+   $dbxref = db_fetch_object(db_query($dbxsql,$db_id,$accession));
+   if(!$dbxref){
+      $sql = "
+         INSERT INTO {dbxref} (db_id, accession, version, description)
+         VALUES (%d,'%s','%s','%s')
+      ";
+      if(!db_query($sql,$db_id,$accession,$version,$description)){
+         print "Failed to insert the dbxref record $accession\n";
+         return 0;
+      }
+      $dbxref = db_fetch_object(db_query($dbxsql,$db_id,$accession));
+   }
+   return $dbxref;
+
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_parse($obo_file,&$obo,&$header){
+   $i = 0;
+   $in_header = 1;
+   $stanza = array();
+
+   // iterate through the lines in the OBO file and parse the stanzas
+   $fh = fopen($obo_file,'r');
+   while($line = fgets($fh)) {
+      $i++;
+
+      // remove newlines
+      $line = rtrim($line);  
+      // skip empty lines
+      if(strcmp($line,'')==0) { continue; }
+      //remove comments from end of lines
+      $line = preg_replace('/^(.*?)\!.*$/','\1',$line);  // TODO: if the explamation is escaped
+
+      if(preg_match('/^\s*\[/',$line)){  // at the first stanza we're out of header
+         $in_header = 0;
+         // load the stanza we just finished reading
+         if(sizeof($stanza) > 0){
+            if(!isset($obo[$type])){
+               $obo[$type] = array();
+            }
+            if(!isset($obo[$type][$stanza['id'][0]])){
+               $obo[$type][$stanza['id'][0]] = $stanza;
+            } else {
+               array_merge($obo[$type][$stanza['id'][0]],$stanza);
+            }
+         } 
+         // get the stanza type:  Term, Typedef or Instance
+         $type = preg_replace('/^\s*\[\s*(.+?)\s*\]\s*$/','\1',$line);
+
+         // start fresh with a new array
+         $stanza = array();
+         continue;
+      }
+      // break apart the line into the tag and value but ignore any escaped colons
+      preg_replace("/\\:/","|-|-|",$line); // temporarily replace escaped colons
+      $pair = explode(":",$line,2);
+      $tag = $pair[0];
+      $value = ltrim(rtrim($pair[1]));// remove surrounding spaces
+      $tag = preg_replace("/\|-\|-\|/","\:",$tag); // return the escaped colon
+      $value = preg_replace("/\|-\|-\|/","\:",$value);
+      if($in_header){
+         if(!isset($header[$tag])){
+            $header[$tag] = array();
+         }
+         $header[$tag][] = $value;
+      } else {
+         if(!isset($stanza[$tag])){
+            $stanza[$tag] = array();
+         }  
+         $stanza[$tag][] = $value;
+      }          
+   }
+   // now add the last term in the file
+   if(sizeof($stanza) > 0){
+      if(!isset($obo[$type])){
+         $obo[$type] = array();
+      }
+      if(!isset($obo[$type][$stanza['id'][0]])){
+         $obo[$type][$stanza['id'][0]] = $stanza;
+      } else {
+         array_merge($obo[$type][$stanza['id'][0]],$stanza);
+      }
+   }
+}
+
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_loader_done (){
+   // return the search path to normal
+   db_query("set search_path to public");  
+   return '';
+}

+ 48 - 0
tripal_cv/tripal_cv.install

@@ -16,6 +16,7 @@ function tripal_cv_install(){
       db_query($sql);
    }
    db_set_active($previous_db);
+
    // Create the MView
    tripal_add_mview(
       // view name
@@ -40,8 +41,30 @@ function tripal_cv_install(){
       ''
    );
 
+   // create the tables that correlate OBO files/references with a chado CV
+   drupal_install_schema('tripal_cv');
+
 }
+/*******************************************************************************
+*  This update adds the new tripal_obo table.  This is an upgrade from
+*  Tripal version 0.2
+*/
 
+function tripal_cv_update_6000(){
+   drupal_install_schema('tripal_cv');
+   $ret = array(
+      '#finished' => 1,
+   );
+   
+   return $ret;
+}
+/************************************************************************
+* Implementation of hook_schema().
+*/
+function tripal_cv_schema() {
+   $schema = tripal_cv_get_schemas();
+   return $schema;
+}
 /*******************************************************************************
 * Implementation of hook_uninstall()
 */
@@ -52,6 +75,8 @@ function tripal_cv_uninstall(){
    if($mview){
 	   tripal_mviews_action('delete',$mview);
 	}
+
+   drupal_uninstall_schema('tripal_cv');
 }
 
 /*******************************************************************************
@@ -71,3 +96,26 @@ function tripal_cv_requirements($phase) {
    }
    return $requirements;
 }
+/************************************************************************
+* This function simply defines all tables needed for the module to work
+* correctly.  By putting the table definitions in a separate function we 
+* can easily provide the entire list for hook_install or individual
+* tables for an update.
+*/
+function tripal_cv_get_schemas (){  
+  $schema = array();
+
+  $schema['tripal_obo'] = array(
+      'fields' => array(
+         'cv_id' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
+         'file'  => array('type' => 'varchar','length' => 1024),
+         'url'   => array('type' => 'varchar','length' => 1024),
+      ),
+      'indexes' => array(
+         'cv_id' => array('cv_id')
+       ),
+      'primary key' => array('cv_id'),
+  );
+
+  return $schema;
+}

+ 196 - 88
tripal_cv/tripal_cv.module

@@ -2,6 +2,7 @@
 
 require_once "charts.php";
 require_once "trees.php";
+require_once "obo_loader.php";
 
 //
 // Copyright 2009 Clemson University
@@ -47,7 +48,14 @@ function tripal_cv_menu() {
    $items['admin/tripal/tripal_cv/new'] = array(
      'title' => 'Add a Controlled Vocabulary',
      'page callback' => 'drupal_get_form',
-     'page arguments' => array('tripal_cv_form'),
+     'page arguments' => array('tripal_cv_add_form'),
+     'access arguments' => array('access administration pages'),
+     'type' => MENU_NORMAL_ITEM,
+   );
+   $items['admin/tripal/tripal_cv/obo'] = array(
+     'title' =>'Upload an OBO File',
+     'page callback' => 'drupal_get_form',
+     'page arguments' => array('tripal_cv_obo_form'),
      'access arguments' => array('access administration pages'),
      'type' => MENU_NORMAL_ITEM,
    );
@@ -167,9 +175,11 @@ function tripal_cv_perm(){
 */
 function tripal_cv_admin_page(){
    $add_url = url("admin/tripal/tripal_cv/new");
+   $obo_url = url("admin/tripal/tripal_cv/obo");
    $cvtermpath_url = url("admin/tripal/tripal_cv/cvtermpath");
    $browser_url = url("cv_browser");
    $output = "<a href=\"$add_url\">Add a new controlled vocabulary</a> | ";
+   $output = "<a href=\"$obo_url\">Upload an OBO file</a> | ";
    $output .= "<a href=\"$cvtermpath_url\">Update the cvtermpath table</a> | ";
    $output .= "<a href=\"$browser_url\">Browse a vocabulary</a> ";    
    $output .= drupal_get_form('tripal_cv_select_form');
@@ -214,50 +224,127 @@ function tripal_cv_select_form(){
 function tripal_ajax_cv_edit (){ 
    // get the database id, build the form and then return the JSON object
    $cvid = $_POST['cvid'];
-   $form = drupal_get_form('tripal_cv_form',$cvid);
+   $form = drupal_get_form('tripal_cv_edit_form',$cvid);
    drupal_json(array('status' => TRUE, 'data' => $form));
 }
 /*************************************************************************
 *
 */
-function tripal_cv_form(&$form_state = NULL,$cvid = NULL){
+function tripal_cv_add_form(&$form_state = NULL){
 
-   // get this requested database
-   if($cvid){
-      $sql = "SELECT * FROM {cv} WHERE cv_id = %d ";
-      $previous_db = db_set_active('chado');
-      $cv = db_fetch_object(db_query($sql,$cvid));
-      db_set_active($previous_db);
+
+   $form['cvid'] = array(
+      '#type' => 'hidden',
+      '#value' => $cvid
+   );
 
 
-      # set the default values.  If there is a value set in the 
-      # form_state then let's use that, otherwise, we'll pull 
-      # the values from the database 
-      $default_db = $form_state['values']['name'];
-      $default_desc = $form_state['values']['description'];
-      $default_url = $form_state['values']['url'];
-      $default_urlprefix = $form_state['values']['urlprefix'];
-      if(!$default_db){
-         $default_cv = $cv->name;
-      }
-      if(!$default_desc){
-         $default_desc = $cv->definition;
-      }
-      $action = 'Update';
-   } else {
-      $action = 'Add';
+   $form['name']= array(
+      '#type'          => 'textfield',
+      '#title'         => t("Controlled Vocabulary name"),
+      '#description'   => t('Please enter the name for this vocabulary.  This field will be ignored if an OBO file or URL is provided above'),
+      '#required'      => FALSE,
+      '#default_value' => $default_cv,
+      '#weight'        => 1
+   );
+
+   $form['definition']= array(
+      '#type'          => 'textarea',
+      '#title'         => t('Description'),
+      '#description'   => t('Please enter a description for this vocabulary'),
+      '#default_value' => $default_desc,
+      '#weight'        => 2
+   );
+
+
+   $form['add'] = array (
+     '#type'         => 'submit',
+     '#value'        => t('Add'),
+     '#weight'       => 5,
+     '#executes_submit_callback' => TRUE,
+   );
+
+   $form['#redirect'] = 'admin/tripal/tripal_cv';
+
+
+   return $form;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_obo_form(&$form_state = NULL){
+
+
+   $form['obo_url']= array(
+      '#type'          => 'textfield',
+      '#title'         => t('Remote OBO v1.2 Definition File'),
+      '#description'   => t('Please enter a URL the points to online OBO file.  The file will be downloaded and parsed. 
+                             All necessary information for naming of the conrolled vocabulary is contained in the file.
+                             If the specification file contains more than one vocabulary then each will be created.'),
+      '#default_value' => $default_desc,
+      '#weight'        => -1
+   );
+   $form['obo_file']= array(
+      '#type'          => 'textfield',
+      '#title'         => t('Local OBO v1.2 Definition File'),
+      '#description'   => t('Please enter the full path for an OBO definition file.  The path must be accessible to the
+                             server on which this Drupal instance is running.  All necessary information for naming of the
+                             controlled vocabulary is contained in this file.  If the specification file contains more than 
+                             one vocabulary then each will be created.'),
+      '#default_value' => $default_desc,
+      '#weight'        => 0
+   );
+
+
+   $form['upload'] = array (
+     '#type'         => 'submit',
+     '#value'        => t('Upload'),
+     '#weight'       => 5,
+     '#executes_submit_callback' => TRUE,
+   );
+
+   $form['#redirect'] = 'admin/tripal/tripal_cv';
+
+
+   return $form;
+}
+/*************************************************************************
+*
+*/
+function tripal_cv_edit_form(&$form_state = NULL,$cvid = NULL){
+
+  
+   $sql = "SELECT * FROM {cv} WHERE cv_id = %d ";
+   $previous_db = db_set_active('chado');
+   $cv = db_fetch_object(db_query($sql,$cvid));
+   db_set_active($previous_db);
+
+
+   # set the default values.  If there is a value set in the 
+   # form_state then let's use that, otherwise, we'll pull 
+   # the values from the database 
+   $default_db = $form_state['values']['name'];
+   $default_desc = $form_state['values']['description'];
+   $default_url = $form_state['values']['url'];
+   $default_urlprefix = $form_state['values']['urlprefix'];
+   if(!$default_db){
+      $default_cv = $cv->name;
    }
+   if(!$default_desc){
+      $default_desc = $cv->definition;
+   }
+ 
 
    $form['cvid'] = array(
       '#type' => 'hidden',
       '#value' => $cvid
    );
-
+ 
    $form['name']= array(
       '#type'          => 'textfield',
       '#title'         => t("Controlled Vocabulary name"),
       '#description'   => t('Please enter the name for this vocabulary.'),
-      '#required'      => TRUE,
+      '#required'      => FALSE,
       '#default_value' => $default_cv,
       '#weight'        => 1
    );
@@ -270,27 +357,19 @@ function tripal_cv_form(&$form_state = NULL,$cvid = NULL){
       '#weight'        => 2
    );
 
-   if(strcmp($action,'Update')==0){
-      $form['update'] = array (
-        '#type'         => 'submit',
-        '#value'        => t('Update'),
-        '#weight'       => 5,
-        '#executes_submit_callback' => TRUE,
-      );
-      $form['delete'] = array (
-        '#type'         => 'submit',
-        '#value'        => t('Delete'),
-        '#weight'       => 6,
-        '#executes_submit_callback' => TRUE,
-      );
-   } else {
-      $form['add'] = array (
-        '#type'         => 'submit',
-        '#value'        => t('Add'),
-        '#weight'       => 5,
-        '#executes_submit_callback' => TRUE,
-      );
-   }
+   $form['update'] = array (
+     '#type'         => 'submit',
+     '#value'        => t('Update'),
+     '#weight'       => 5,
+     '#executes_submit_callback' => TRUE,
+   );
+   $form['delete'] = array (
+     '#type'         => 'submit',
+     '#value'        => t('Delete'),
+     '#weight'       => 6,
+     '#executes_submit_callback' => TRUE,
+   );
+
    $form['#redirect'] = 'admin/tripal/tripal_cv';
 
 
@@ -299,61 +378,90 @@ function tripal_cv_form(&$form_state = NULL,$cvid = NULL){
 /************************************************************************
 *
 */
-function tripal_cv_form_submit($form, &$form_state){
+function tripal_cv_edit_form_submit($form, &$form_state){
 
    $name =  $form_state['values']['name'];
    $desc =  $form_state['values']['definition'];
    $cvid =  $form_state['values']['cvid'];
    $op   =  $form_state['values']['op'];
-
-   if($cvid){ 
-      if(strcmp($op,'Update')==0){
-         $sql = "
-            UPDATE {cv} SET 
-              name = '%s',
-              definition = '%s'
-            WHERE cv_id = %d
-         ";
-         $previous_db = db_set_active('chado');
-         $db = db_query($sql,$name,$desc,$cvid);
-         db_set_active($previous_db);
-         if($db){
-           drupal_set_message("Controlled vocabulary updated");
-         } else {
-           drupal_set_message("Failed to update controlled vocabulary.");
-         }
-      } 
-      if(strcmp($op,'Delete')==0){
-         $sql = "
-            DELETE FROM {cv}
-            WHERE cv_id = %d
-         ";
-         $previous_db = db_set_active('chado');
-         $db = db_query($sql,$cvid);
-         db_set_active($previous_db);
-         if($db){
-           drupal_set_message("Controlled vocabulary deleted");
-         } else {
-           drupal_set_message("Failed to delete controlled vocabulary.");
-         }
+  
+   if(strcmp($op,'Update')==0){
+      $sql = "
+         UPDATE {cv} SET 
+           name = '%s',
+           definition = '%s'
+         WHERE cv_id = %d
+      ";
+      $previous_db = db_set_active('chado');
+      $db = db_query($sql,$name,$desc,$cvid);
+      db_set_active($previous_db);
+      if($db){
+        drupal_set_message("Controlled vocabulary updated");
+      } else {
+        drupal_set_message("Failed to update controlled vocabulary.");
       }
    } 
-   else { 
+   if(strcmp($op,'Delete')==0){
       $sql = "
-         INSERT INTO {cv}
-          (name,definition)
-         VALUES 
-          ('%s','%s')
+         DELETE FROM {cv}
+         WHERE cv_id = %d
       ";
       $previous_db = db_set_active('chado');
-      $db = db_query($sql,$name,$desc);
+      $db = db_query($sql,$cvid);
       db_set_active($previous_db);
       if($db){
-        drupal_set_message("External database added");
+        drupal_set_message("Controlled vocabulary deleted");
       } else {
-        drupal_set_message("Failed to add external database.");
+        drupal_set_message("Failed to delete controlled vocabulary.");
       }
+   }
+
+
+   return '';
+}
+/************************************************************************
+*
+*/
+function tripal_cv_add_form_submit($form, &$form_state){
+
+   $name =  $form_state['values']['name'];
+   $desc =  $form_state['values']['definition'];
+
+   $sql = "
+      INSERT INTO {cv}
+       (name,definition)
+      VALUES 
+       ('%s','%s')
+   ";
+   $previous_db = db_set_active('chado');
+   $db = db_query($sql,$name,$desc);
+   db_set_active($previous_db);
+   if($db){
+     drupal_set_message("Controlled vocabulary added");
+   } else {
+     drupal_set_message("Failed to add controlled vocabulary.");
+   }
+
+
+   return '';
+}
+/************************************************************************
+*
+*/
+function tripal_cv_obo_form_submit($form, &$form_state){
+   global $user;
+
+   $obo_url =  $form_state['values']['obo_url'];
+   $obo_file  = $form_state['values']['obo_file'];
+
+   if($obo_url){ 
+   }
+   elseif($obo_file){
+      $args = array($obo_file);
+      tripal_add_job("Load OBO $file",'tripal_cv',
+         "tripal_cv_load_obo_v1_2",$args,$user->uid);
    } 
+ 
 
    return '';
 }