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.
# 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.
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.
my $relationship;
if( $self->graph->has_edge_attribute( @vector, 'object' ) ) {
$relationship = $self->graph->get_edge_attribute( @vector, 'object' );
- }
+ }
return $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.
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 }
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";
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