Commit | Line | Data |
b15511bf |
1 | package Text::Tradition::Collation::Segment; |
2 | |
3 | use Moose; |
4 | use MooseX::NonMoose; |
910a0a6d |
5 | use Text::Tradition::Collation::Position; |
b15511bf |
6 | |
7 | extends 'Graph::Easy::Node'; |
8 | |
9 | # A segment is a special 'invisible' node that is a set of Readings. |
10 | # We should never display these, but it is useful to have them |
11 | # available for many-to-many relationship mappings. |
12 | |
13 | has 'members' => ( |
14 | is => 'rw', |
15 | isa => 'ArrayRef[Text::Tradition::Collation::Reading]', |
16 | required => 1, |
17 | ); |
18 | |
910a0a6d |
19 | has 'position' => ( |
20 | is => 'rw', |
21 | isa => 'Text::Tradition::Collation::Position', |
22 | predicate => 'has_position', |
23 | ); |
24 | |
b15511bf |
25 | sub FOREIGNBUILDARGS { |
26 | my $class = shift; |
27 | my %args = @_; |
28 | |
29 | # Name the segment after its member elements. |
30 | my $nodename = join( ' ', map { $_->name } @{$args{'members'}} ); |
31 | return ( 'name', $nodename ); |
32 | } |
33 | |
34 | sub BUILD { |
35 | my( $self, $args ) = @_; |
36 | $self->set_attribute( 'class', 'segment' ); |
910a0a6d |
37 | my $ctr = 1; |
38 | foreach my $r ( @{$args->{members}} ) { |
39 | my $seg_edge = $r->parent->add_edge( $r, $self, $ctr++ ); |
40 | $seg_edge->set_attribute( 'class', 'segment' ); |
41 | } |
42 | unless ( grep { !$_->has_position } @{$args->{members}} ) { |
43 | $self->set_position; |
44 | } |
45 | } |
b15511bf |
46 | |
910a0a6d |
47 | # We use our 'members' array for the initialization, but afterward we |
48 | # go by graph edges. This ensures that merged nodes stay merged. |
49 | around 'members' => sub { |
50 | my $orig = shift; |
51 | my $self = shift; |
52 | my @members; |
53 | foreach my $sl ( sort { $a->name <=> $b->name } |
54 | grep { $_->sub_class eq 'segment' } $self->incoming ) { |
55 | push( @members, $sl->from ); |
56 | } |
57 | return \@members; |
58 | }; |
59 | |
60 | sub set_position { |
61 | my $self = shift; |
62 | my( $common, $min, $max ); |
63 | my $readings = $self->members; |
b15511bf |
64 | foreach my $r ( @{$self->members} ) { |
910a0a6d |
65 | if( $r->has_position ) { |
66 | if( $common && $common != $r->position->common ) { |
67 | warn "Segment adding node with position skew"; |
68 | } elsif( !$common ) { |
69 | $common = $r->position->common; |
70 | } |
71 | $min = $r->position->min unless $min && $min < $r->position->min; |
72 | $max = $r->position->max unless $max && $max > $r->position->max; |
73 | } else { |
74 | warn "Called set_position on segment which has an unpositioned reading"; |
75 | } |
b15511bf |
76 | } |
910a0a6d |
77 | $self->position( Text::Tradition::Collation::Position->new( |
78 | common => $common, min => $min, max => $max |
79 | ) ); |
b15511bf |
80 | } |
910a0a6d |
81 | sub neighbor_readings { |
82 | my( $self, $direction ) = @_; |
83 | $direction = 'both' unless $direction; |
84 | my @answer; |
85 | if( $direction !~ /^back/ ) { |
86 | # We want forward readings. |
87 | push( @answer, $self->members->[0]->neighbor_readings( 'forward' ) ); |
88 | } |
89 | if( $direction ne 'forward' ) { |
90 | # We want backward readings. |
91 | push( @answer, $self->members->[0]->neighbor_readings( 'back' ) ); |
92 | } |
93 | return @answer; |
b15511bf |
94 | } |
95 | |
96 | no Moose; |
97 | __PACKAGE__->meta->make_immutable; |
98 | |
99 | 1; |
100 | |
101 | ###################################################### |
102 | ## copied from Graph::Easy::Parser docs |
103 | ###################################################### |
104 | # when overriding nodes, we also need ::Anon |
105 | |
106 | package Text::Tradition::Collation::Segment::Anon; |
107 | use Moose; |
108 | use MooseX::NonMoose; |
109 | extends 'Text::Tradition::Collation::Segment'; |
110 | extends 'Graph::Easy::Node::Anon'; |
111 | no Moose; |
112 | __PACKAGE__->meta->make_immutable; |
113 | |
114 | 1; |
115 | # use base qw/Text::Tradition::Collation::Segment/; |
116 | # use base qw/Graph::Easy::Node::Anon/; |
117 | |
118 | ###################################################### |
119 | # and :::Empty |
120 | |
121 | package Text::Tradition::Collation::Segment::Empty; |
122 | use Moose; |
123 | use MooseX::NonMoose; |
124 | extends 'Graph::Easy::Node::Empty'; |
125 | no Moose; |
126 | __PACKAGE__->meta->make_immutable; |
127 | |
128 | 1; |
129 | # use base qw/Text::Tradition::Collation::Segment/; |
130 | |
131 | ###################################################### |