X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FText%2FTradition%2FCollation%2FRelationship.pm;h=422c0c14608f9dc77c398530f6ec1142a31dc12c;hb=a7f4020a1a1fd72aba6e25dc0a8f8aa9a1891202;hp=49ac1dba34ccafd2d460e7a8801a77be10907120;hpb=b15511bfc5546fb21b191921506253f89f19465a;p=scpubgit%2Fstemmatology.git diff --git a/lib/Text/Tradition/Collation/Relationship.pm b/lib/Text/Tradition/Collation/Relationship.pm index 49ac1db..422c0c1 100644 --- a/lib/Text/Tradition/Collation/Relationship.pm +++ b/lib/Text/Tradition/Collation/Relationship.pm @@ -2,91 +2,150 @@ package Text::Tradition::Collation::Relationship; use Moose; use Moose::Util::TypeConstraints; -## CAREFUL in our use of Moose::Util::TypeConstraints. That 'from' -## clashes with Graph::Easy::Edge 'from', so we'll need to unimport -## TypeConstraints after defining the types. Or else we would have to -## finally split out our types into another module. -use MooseX::NonMoose; - -extends 'Graph::Easy::Edge'; - -enum 'RelationshipType' => qw( spelling orthographic grammatical repetition lexical ); - -subtype 'RelationshipVector', - => as 'ArrayRef', - => where { @$_ == 2 - && $_->[0]->isa( 'Graph::Easy::Node' ) - && $_->[1]->isa( 'Graph::Easy::Node' ) - }, - message { 'Argument should be [ SourceReading, TargetReading ]' }; - -subtype 'RelationshipTokenVector', - => as 'ArrayRef', - => where { @$_ == 2 }, - message { 'Argument should be [ \'source\', \'target\' ]' }; - -no Moose::Util::TypeConstraints; ## see comment above - -has 'sort' => ( - is => 'rw', - isa => 'RelationshipType', - required => 1, -); - -has 'orig_relation' => ( - is => 'rw', - isa => 'RelationshipVector', - required => 1, -); - -has 'related_readings' => ( - is => 'rw', - isa => 'RelationshipTokenVector', -); - -has 'global' => ( - is => 'rw', - isa => 'Bool', - default => 0, -); + +enum 'RelationshipType' => qw( spelling orthographic grammatical lexical + collated repetition transposition ); + +enum 'RelationshipScope' => qw( local document global ); + +no Moose::Util::TypeConstraints; + +=head1 NAME + +Text::Tradition::Collation::Relationship - represents a syntactic or semantic +relationship between two readings + +=head1 DESCRIPTION + +Text::Tradition is a library for representation and analysis of collated +texts, particularly medieval ones. A relationship connects two readings +within a collation, usually when they appear in the same place in different +texts. + +=head1 CONSTRUCTOR + +=head2 new + +Creates a new relationship. Usually called via $collation->add_relationship. +Options include: + +=over 4 + +=item * type - Can be one of spelling, orthographic, grammatical, lexical, +collated, repetition, transposition. All but the last two are only valid +relationships between readings that occur at the same point in the text. +The 'collated' relationship should only be used by parsers to align readings +in the graph when the input information would otherwise be lost, e.g. from +an alignment table. + +=item * displayform - (Optional) The reading that should be displayed if the +related nodes are treated as one. + +=item * scope - (Optional) A meta-attribute. Can be one of 'local', +'document', or 'global'. Denotes whether the relationship between the two +readings holds always, independent of context, either within this tradition +or across all traditions. + +=item * annotation - (Optional) A freeform note to attach to the relationship. + +=item * non_correctable - (Optional) True if the reading would not have been +corrected independently. + +=item * non_independent - (Optional) True if the variant is unlikely to have +occurred independently in unrelated witnesses. + +=back + +=head1 ACCESSORS + +=head2 type + +=head2 displayform + +=head2 scope + +=head2 annotation + +=head2 non_correctable + +=head2 non_independent + +See the option descriptions above. + +=cut + +has 'type' => ( + is => 'ro', + isa => 'RelationshipType', + required => 1, + ); + +has 'reading_a' => ( + is => 'ro', + isa => 'Str', + required => 1, + ); + +has 'reading_b' => ( + is => 'ro', + isa => 'Str', + required => 1, + ); + +has 'displayform' => ( + is => 'ro', + isa => 'Str', + predicate => 'has_displayform', + ); + +has 'scope' => ( + is => 'ro', + isa => 'RelationshipScope', + default => 'local', + ); + +has 'annotation' => ( + is => 'ro', + isa => 'Str', + predicate => 'has_annotation', + ); has 'non_correctable' => ( - is => 'rw', - isa => 'Bool', - ); + is => 'ro', + isa => 'Bool', + ); has 'non_independent' => ( - is => 'rw', - isa => 'Bool', - ); - -sub FOREIGNBUILDARGS { - my $class = shift; - my %args = @_; - - # Make the label match our 'sort' attribute. - my @superclass_args; - if( exists $args{'sort'} ) { - push( @superclass_args, 'label', $args{'sort'} ); - } - return @superclass_args; + is => 'ro', + isa => 'Bool', + ); + +# A read-only meta-Boolean attribute. + +=head2 colocated + +Returns true if the relationship type is one that requires that its readings +occupy the same place in the collation. + +=cut + +sub colocated { + my $self = shift; + return $self->type !~ /^(repetition|transposition)$/; } -sub BUILD { - my( $self, $args ) = @_; +=head2 nonlocal - $self->set_attribute( 'class', 'relationship' ); +Returns true if the relationship scope is anything other than 'local'. - my( $source, $target ) = @{$self->orig_relation}; - if( $source->has_position && $target->has_position - && $source->position ne $target->position ) { - die "Cannot set relationship between readings in different positions"; - } - unless( $self->related_readings ) { - $self->related_readings( [ $self->orig_relation->[0]->label, - $self->orig_relation->[1]->label ] ); - } +=cut + +sub nonlocal { + my $self = shift; + return $self->scope ne 'local'; } no Moose; __PACKAGE__->meta->make_immutable; + +1;