From d755a1b3b6ace5be649a2455dcc456417a390784 Mon Sep 17 00:00:00 2001
From: Will Spooner <whs@sanger.ac.uk>
Date: Fri, 9 Feb 2007 17:22:11 +0000
Subject: [PATCH] Added store_mapping_path method to add assembly.mapping
 entries to the meta table

---
 .../Bio/EnsEMBL/DBSQL/CoordSystemAdaptor.pm   | 103 +++++++++++++++++-
 1 file changed, 101 insertions(+), 2 deletions(-)

diff --git a/modules/Bio/EnsEMBL/DBSQL/CoordSystemAdaptor.pm b/modules/Bio/EnsEMBL/DBSQL/CoordSystemAdaptor.pm
index c0d9d1cb01..c2c5c19323 100644
--- a/modules/Bio/EnsEMBL/DBSQL/CoordSystemAdaptor.pm
+++ b/modules/Bio/EnsEMBL/DBSQL/CoordSystemAdaptor.pm
@@ -183,13 +183,19 @@ sub new {
   }
   $sth->finish();
 
+  $self->_cache_mapping_paths;
 
 
+  return $self;
+}
+
+sub _cache_mapping_paths{
   #
   # Retrieve a list of available mappings from the meta table.
   # this may eventually be moved a table of its own if this proves too
   # cumbersome
   #
+  my $self = shift;
 
   my %mapping_paths;
   my $mc = $self->db()->get_MetaContainer();
@@ -252,11 +258,10 @@ sub new {
 
   $self->{'_mapping_paths'} = \%mapping_paths;
 
-  return $self;
+  return 1;                           
 }
 
 
-
 =head2 fetch_all
 
   Arg [1]    : none
@@ -666,6 +671,100 @@ sub get_mapping_path {
   return $path || [];
 }
 
+=head2 store_mapping_path
+
+  Arg [1]    : Bio::EnsEMBL::CoordSystem $cs1
+  Arg [2]    : Bio::EnsEMBL::CoordSystem $cs2
+  Arg [3..n] : Bio::EnsEMBL::CoordSystems $cs3..$csN
+  Example    : my $pathref = $csa->store_mapping_path($cs1,$cs2);
+  Description: Given two or more coordinate systems this will store 
+               mapping paths between them in the database. 
+
+               The 'rank' attrib of the CoordSystems is used to
+               determine the assembled/component relationships between
+               them.
+
+               For example, if $cs1 represents chrs of version
+               V1, $cs2 represents contigs, and $cs3 clones then, unless
+               they already exist, the following entries will be created 
+               in the meta table;
+               +------------------+---------------------+ 
+               | meta_key         | meta_value          |
+               +------------------+---------------------+ 
+               | assembly.mapping | chr:V1|clone        |
+               | assembly.mapping | clone|contig        |
+               | assembly.mapping | chr:V1|clone|contig |
+               +------------------+---------------------+
+
+
+               For a one-step mapping path to be valid there needs to be
+               a relationship between the two coordinate systems defined in
+               the assembly table.  Two step mapping paths work by building
+               on the one-step mapping paths which are already defined.
+
+               The first coordinate system in a one step mapping path must
+               be the assembled coordinate system and the second must be
+               the component.
+
+  Returntype : reference to a list of lists of new meta_value mapping strings
+               created for assembly.mapping
+  Exceptions : CoordSystems with no rank/duplicated rank
+  Caller     : general
+  Status     : Experimental
+
+=cut
+
+sub store_mapping_path{
+  my $self = shift;
+  my @csystems = @_;
+
+  # Validate and sort the args
+  my %seen_ranks;
+  @csystems >= 2 or throw('Need two or more CoordSystems');
+  my $validate = sub{ 
+    ref($_[0]) && $_[0]->isa('Bio::EnsEMBL::CoordSystem') or
+        throw('CoordSystem argument expected.');
+    my $rank = $_[0]->rank || 
+        throw('CoordSystem has no rank: '.$_[0]->name);
+    $seen_ranks{$rank} &&
+        throw('CoordSystem '.$_[0]->name." shares rank $rank with ".
+              $seen_ranks{$rank}->name);
+    $seen_ranks{$rank} = $_[0];
+  };
+  @csystems = sort{$a->rank <=> $b->rank} map{&{$validate}($_)} @csystems;
+
+  # Get a list of all existing assembly.mappings
+  #my %mappings = map{$_=>1} @{$meta->list_value_by_key('assembly.mapping')};
+  
+  # For each pair in the sorted list, store in the DB
+  my $meta = $self->db->get_MetaContainer;
+  my @retlist;
+  for( my $i=1; $i<@csystems; $i++ ){
+    for( my $j=0; $j<(@csystems-$i); $j++ ){
+      my $mapping = join( "|", 
+                          map{join( ':', $_->name, ($_->version||()) )} 
+                          @csystems[$j..$j+$i] );
+      my $mapping_key = join( "|",
+                              map{join( ':', $_->name, ($_->version||'') )}
+                              @csystems[$j..$j+$i] );
+      # Skip existing
+      next if $self->{'_mapping_paths'}->{$mapping_key};
+      
+      # Update the database
+      $meta->store_key_value('assembly.mapping',$mapping);
+      push @retlist, $mapping;
+    }
+  }
+
+  if( @retlist ){
+    # Update mapping path cache
+    $self->_cache_mapping_paths;
+  }
+
+  # Return the mappings that we have just created
+  return [@retlist];
+}
+
 
 sub _fetch_by_attrib {
   my $self = shift;
-- 
GitLab