From: Tara L Andrews Date: Fri, 24 Feb 2012 01:06:55 +0000 (+0100) Subject: handle some cases for existing scoped relationships etc. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=ca6e6095920ad91d131ee8365872ca8501849f08;p=scpubgit%2Fstemmatology.git handle some cases for existing scoped relationships etc. --- diff --git a/lib/Text/Tradition/Collation.pm b/lib/Text/Tradition/Collation.pm index 9eac271..9ec858e 100644 --- a/lib/Text/Tradition/Collation.pm +++ b/lib/Text/Tradition/Collation.pm @@ -437,6 +437,17 @@ sub add_relationship { return @vectors; } +around qw/ get_relationship del_relationship / => sub { + my $orig = shift; + my $self = shift; + my @args = @_; + if( @args == 1 && ref( $args[0] ) eq 'ARRAY' ) { + @args = @{$_[0]}; + } + my( $source, $target ) = $self->_stringify_args( @args ); + $self->$orig( $source, $target ); +}; + =head2 reading_witnesses( $reading ) Return a list of sigils corresponding to the witnesses in which the reading appears. @@ -1355,7 +1366,7 @@ sub calculate_ranks { # Do we need to invalidate the cached data? if( $self->has_cached_svg || $self->has_cached_table ) { foreach my $r ( $self->readings ) { - next if $existing_ranks{$r} == $r->rank; + next if $existing_ranks{$r} && $existing_ranks{$r} == $r->rank; # Something has changed, so clear the cache $self->_clear_cache; # ...and recalculate the common readings. diff --git a/lib/Text/Tradition/Collation/Reading.pm b/lib/Text/Tradition/Collation/Reading.pm index 907310d..4f02376 100644 --- a/lib/Text/Tradition/Collation/Reading.pm +++ b/lib/Text/Tradition/Collation/Reading.pm @@ -116,6 +116,7 @@ has 'rank' => ( is => 'rw', isa => 'Int', predicate => 'has_rank', + clearer => 'clear_rank', ); ## For prefix/suffix readings diff --git a/lib/Text/Tradition/Collation/RelationshipStore.pm b/lib/Text/Tradition/Collation/RelationshipStore.pm index 3328b96..0f48552 100644 --- a/lib/Text/Tradition/Collation/RelationshipStore.pm +++ b/lib/Text/Tradition/Collation/RelationshipStore.pm @@ -86,24 +86,9 @@ has 'graph' => ( relationships => 'edges', add_reading => 'add_vertex', delete_reading => 'delete_vertex', - delete_relationship => 'delete_edge', }, ); -around 'delete_relationship' => sub { - my $orig = shift; - my $self = shift; - my @vector; - if( @_ == 1 && ref( $_[0] ) eq 'ARRAY' ) { - # Dereference the edge arrayref that was passed. - my $edge = shift; - @vector = @$edge; - } else { - @vector = @_; - } - return $self->$orig( @vector ); -}; - =head2 get_relationship Return the relationship object, if any, that exists between two readings. @@ -123,7 +108,7 @@ sub get_relationship { my $relationship; if( $self->graph->has_edge_attribute( @vector, 'object' ) ) { $relationship = $self->graph->get_edge_attribute( @vector, 'object' ); - } + } return $relationship; } @@ -133,11 +118,6 @@ sub _set_relationship { $self->graph->set_edge_attribute( @vector, 'object', $relationship ); } -sub _remove_relationship { - my( $self, @vector ) = @_; - $self->graph->delete_edge( @vector ); -} - =head2 create Create a new relationship with the given options and return it. @@ -228,25 +208,41 @@ add_relationship. sub add_relationship { my( $self, $source, $source_rdg, $target, $target_rdg, $options ) = @_; - # Check the options - $options->{'scope'} = 'local' unless $options->{'scope'}; - - my( $is_valid, $reason ) = - $self->relationship_valid( $source, $target, $options->{'type'} ); - unless( $is_valid ) { - throw( "Invalid relationship: $reason" ); + my $relationship; + my $thispaironly; + if( ref( $options ) eq 'Text::Tradition::Collation::Relationship' ) { + $relationship = $options; + $thispaironly = 1; # If existing rel, set only where asked. + } else { + # Check the options + $options->{'scope'} = 'local' unless $options->{'scope'}; + + my( $is_valid, $reason ) = + $self->relationship_valid( $source, $target, $options->{'type'} ); + unless( $is_valid ) { + throw( "Invalid relationship: $reason" ); + } + + # Try to create the relationship object. + $options->{'reading_a'} = $source_rdg->text; + $options->{'reading_b'} = $target_rdg->text; + $options->{'orig_a'} = $source; + $options->{'orig_b'} = $target; + $relationship = $self->create( $options ); # Will throw on error } - - # Try to create the relationship object. - $options->{'reading_a'} = $source_rdg->text; - $options->{'reading_b'} = $target_rdg->text; - $options->{'orig_a'} = $source; - $options->{'orig_b'} = $target; - my $relationship = $self->create( $options ); # Will throw on error + # Find all the pairs for which we need to set the relationship. my @vectors = ( [ $source, $target ] ); - if( $relationship->colocated && $relationship->nonlocal ) { + if( $relationship->colocated && $relationship->nonlocal && !$thispaironly ) { + # Is there a relationship with this a & b already? + my $otherrel = $self->scoped_relationship( $relationship->reading_a, + $relationship->reading_b ); + if( $otherrel && $otherrel->type eq $relationship->type + && $otherrel->scope eq $relationship->scope ) { + warn "Applying existing scoped relationship"; + $relationship = $otherrel; + } my $c = $self->collation; # Set the same relationship everywhere we can, throughout the graph. my @identical_readings = grep { $_->text eq $relationship->reading_a } @@ -271,8 +267,9 @@ sub add_relationship { my @pairs_set; foreach my $v ( @vectors ) { my $rel = $self->get_relationship( @$v ); - if( $rel ) { + if( $rel && $rel ne $relationship ) { if( $rel->nonlocal ) { + $DB::single = 1; throw( "Found conflicting relationship at @$v" ); } else { warn "Not overriding local relationship set at @$v"; @@ -311,6 +308,11 @@ sub del_relationship { return @vectors; } +sub _remove_relationship { + my( $self, @vector ) = @_; + $self->graph->delete_edge( @vector ); +} + =head2 relationship_valid( $source, $target, $type ) Checks whether a relationship of type $type may exist between the readings given