change calling of enum for RT ticket 90694
[scpubgit/stemmatology.git] / base / lib / Text / Tradition / Collation / Relationship.pm
1 package Text::Tradition::Collation::Relationship;
2
3 use Moose;
4 use Moose::Util::TypeConstraints;
5
6 enum 'RelationshipScope' => [ qw( local document global ) ];
7
8 no Moose::Util::TypeConstraints;
9
10 =head1 NAME
11
12 Text::Tradition::Collation::Relationship - represents a syntactic or semantic
13 relationship between two readings
14     
15 =head1 DESCRIPTION
16
17 Text::Tradition is a library for representation and analysis of collated
18 texts, particularly medieval ones.  A relationship connects two readings
19 within a collation, usually when they appear in the same place in different
20 texts.
21
22 =head1 CONSTRUCTOR
23
24 =head2 new
25
26 Creates a new relationship. Usually called via $collation->add_relationship.
27 Options include:
28
29 =over 4
30
31 =item * type - Can be one of spelling, orthographic, grammatical, lexical, 
32 collated, repetition, transposition.  All but the last two are only valid 
33 relationships between readings that occur at the same point in the text. 
34 The 'collated' relationship should only be used by parsers to align readings 
35 in the graph when the input information would otherwise be lost, e.g. from
36 an alignment table.
37
38 =item * displayform - (Optional) The reading that should be displayed if the 
39 related nodes are treated as one.
40
41 =item * scope - (Optional) A meta-attribute.  Can be one of 'local', 
42 'document', or 'global'. Denotes whether the relationship between the two 
43 readings holds always, independent of context, either within this tradition 
44 or across all traditions.
45
46 =item * annotation - (Optional) A freeform note to attach to the relationship.
47
48 =item * alters_meaning - Indicate whether, in context, the related words cause
49 the text to have different meanings. Possible values are 0 (no), 1 (slightly),
50 and >1 (yes).
51
52 =item * non_correctable - (Optional) True if the reading would not have been 
53 corrected independently.
54
55 =item * non_independent - (Optional) True if the variant is unlikely to have 
56 occurred independently in unrelated witnesses.
57
58 =back
59
60 =head1 ACCESSORS
61
62 =head2 type
63
64 =head2 displayform
65
66 =head2 scope
67
68 =head2 annotation
69
70 =head2 non_correctable
71
72 =head2 non_independent
73
74 See the option descriptions above.
75
76 =cut
77
78 has 'type' => (
79         is => 'ro',
80         isa => 'Str',
81         required => 1,
82         );
83
84 has 'reading_a' => (
85         is => 'ro',
86         isa => 'Str',
87         required => 1,
88         );
89
90 has 'reading_b' => (
91         is => 'ro',
92         isa => 'Str',
93         required => 1,
94         );
95
96 has 'displayform' => (
97         is => 'ro',
98         isa => 'Str',
99         predicate => 'has_displayform',
100         );
101
102 has 'scope' => (
103         is => 'ro',
104         isa => 'RelationshipScope', 
105         default => 'local',
106         );
107         
108 has 'annotation' => (
109         is => 'ro',
110         isa => 'Str',
111         predicate => 'has_annotation',
112         );
113         
114 has 'alters_meaning' => (
115         is => 'rw',
116         isa => 'Int',
117         default => 0,
118         );
119
120 has 'non_correctable' => (
121         is => 'ro',
122         isa => 'Bool',
123         );
124
125 has 'non_independent' => (
126         is => 'ro',
127         isa => 'Bool',
128         );
129         
130 around 'alters_meaning' => sub {
131         my $orig = shift;
132         my $self = shift;
133         if( @_ ) {
134                 if( $_[0] eq 'no' ) {
135                         return $self->$orig( 0 );
136                 } elsif( $_[0] eq 'slightly' ) {
137                         return $self->$orig( 1 );
138                 } elsif( $_[0] eq 'yes' ) {
139                         return $self->$orig( 2 );
140                 } 
141         }
142         return $self->$orig( @_ );
143 };              
144         
145 # A read-only meta-Boolean attribute.
146
147 =head2 colocated
148
149 Returns true if the relationship type is one that requires that its readings
150 occupy the same place in the collation.
151
152 =cut
153
154 sub colocated {
155         my $self = shift;
156         return $self->type !~ /^(repetition|transposition)$/;
157 }
158
159 =head2 nonlocal
160
161 Returns true if the relationship scope is anything other than 'local'.
162
163 =cut
164
165 sub nonlocal {
166         my $self = shift;
167         return $self->scope ne 'local';
168 }
169
170 =head2 is_equivalent( $otherrel )
171
172 Returns true if the type and scope of $otherrel match ours.
173
174 =cut
175
176 sub is_equivalent {
177         my( $self, $other, $check_ann ) = @_;
178         my $oksofar = $self->type eq $other->type && $self->scope eq $other->scope;
179         if( $check_ann ) {
180                 return $oksofar && $self->annotation eq $other->annotation;
181         } else {
182                 return $oksofar;
183         }
184 }
185
186 no Moose;
187 __PACKAGE__->meta->make_immutable;
188
189 1;