make the first couple of tests pass
[scpubgit/stemmatology.git] / lib / Text / Tradition / Collation / Reading.pm
CommitLineData
784877d9 1package Text::Tradition::Collation::Reading;
2
8e1394aa 3use Moose;
d047cd52 4use Moose::Util::TypeConstraints;
784877d9 5use MooseX::NonMoose;
6
7extends 'Graph::Easy::Node';
8
9subtype 'Position'
10 => as 'Str',
11 => where { $_ =~ /^\d+\,\d+$/ },
12 message { 'Position must be of the form x,y' };
13
14has 'position' => (
d047cd52 15 is => 'rw',
16 isa => 'Position',
17 );
784877d9 18
19# This contains an array of reading objects; the array is a pool,
20# shared by the reading objects inside the pool. When a reading is
21# added to the pool, all the same_as attributes should be updated.
22has 'same_as' => (
d047cd52 23 is => 'rw',
24 isa => 'ArrayRef[Text::Tradition::Collation::Reading]',
25 );
784877d9 26
8e1394aa 27# # This is a hash mapping of 'relationship => reading'.
28# # TODO we should validate the relationships sometime.
d047cd52 29has 'relationships' => (
30 is => 'ro',
31 isa => 'HashRef[Text::Tradition::Collation::Reading]',
32 default => sub { {} },
33 );
34
8e1394aa 35# Deal with the non-arg option for Graph::Easy's constructor.
36around BUILDARGS => sub {
37 my $orig = shift;
38 my $class = shift;
39
40 my %args;
41 if( @_ == 1 && ref( $_[0] ) ne 'HASH' ) {
42 return $class->$orig( 'name' => $_[0] );
43 } else {
44 return $class->$orig( @_ );
45 }
46};
47
d047cd52 48# Initialize the identity pool.
49sub BUILD {
50 my( $self, $args ) = @_;
8e1394aa 51 $self->same_as( [ $self ] );
d047cd52 52}
784877d9 53
54sub merge_from {
55 my( $self, $merged_node ) = @_;
56 # Adopt the identity pool of the other node.
57 my @now_identical = grep { $_ ne $merged_node } @{$merged_node->same_as};
58 my $new_pool = _merge_array_pool( \@now_identical, $self->same_as )
59 if @now_identical;
60
d047cd52 61 # Adopt the relationship attributes of the other node.
62 my $now_rel = $merged_node->relationships;
63 foreach my $key ( %$now_rel ) {
784877d9 64 if( $self->has_relationship( $key ) ) {
65 my $related = $self->get_relationship( $key );
d047cd52 66 if( $now_rel->{$key} ne $related ) {
784877d9 67 warn( sprintf( "Merged reading %s has relationship %s to reading %s instead of %s; skipping",
68 $merged_node->name, $key,
d047cd52 69 $now_rel->{$key},
784877d9 70 $related) );
71 } # else no action needed
72 } else {
d047cd52 73 $self->set_relationship( $key, $now_rel->{$key} );
784877d9 74 }
75 }
76}
77
78sub set_identical {
79 my( $self, $other_node ) = @_;
80 my $enlarged_pool = _merge_array_pool( $self->same_as,
81 $other_node->same_as );
82
83 # ...and set this node to point to the enlarged pool.
8e1394aa 84 $self->same_as( $enlarged_pool );
784877d9 85}
86
87sub _merge_array_pool {
88 my( $pool, $main_pool ) = @_;
89 my %poolhash;
90 foreach ( @$main_pool ) {
91 # Note which nodes are already in the main pool so that we
92 # don't re-add them.
93 $poolhash{$_->name} = 1;
94 }
95
96 foreach( @$pool ) {
97 # Add the remaining nodes to the main pool...
98 push( @$main_pool, $_ ) unless $poolhash{$_->name};
99 }
100 return $main_pool;
101}
d047cd52 102
8e1394aa 103sub has_primary {
104 my $self = shift;
105 my $pool = $self->same_as;
106 return $pool->[0]->name eq $self->name;
107}
108
109sub primary {
110 my $self = shift;
111 return $self->same_as->[0];
112}
113
d047cd52 114# Much easier to do this with a hash than with an array of Relationship objects,
115# which would be the proper OO method.
116
117sub has_relationship {
118 my( $self, $rel ) = @_;
119 return exists( $self->relationships->{ $rel } );
120}
121
122sub get_relationship {
123 my( $self, $rel ) = @_;
124 if( $self->has_relationship( $rel ) ) {
125 return $self->relationships->{ $rel };
126 }
127 return undef;
128}
129
130sub set_relationship {
131 my( $self, $rel, $value ) = @_;
132 $self->relationships->{ $rel } = $value;
133}
134
135no Moose;
136__PACKAGE__->meta->make_immutable;
137
1381;
139
140######################################################
141## copied from Graph::Easy::Parser docs
142######################################################
143# when overriding nodes, we also need ::Anon
144
145package Text::Tradition::Collation::Reading::Anon;
021bdbac 146use Moose;
147use MooseX::NonMoose;
148extends 'Text::Tradition::Collation::Reading';
149extends 'Graph::Easy::Node::Anon';
150no Moose;
151__PACKAGE__->meta->make_immutable;
d047cd52 152
021bdbac 1531;
154# use base qw/Text::Tradition::Collation::Reading/;
155# use base qw/Graph::Easy::Node::Anon/;
d047cd52 156
157######################################################
158# and :::Empty
159
160package Text::Tradition::Collation::Reading::Empty;
021bdbac 161use Moose;
162use MooseX::NonMoose;
163extends 'Graph::Easy::Node::Empty';
164no Moose;
165__PACKAGE__->meta->make_immutable;
d047cd52 166
021bdbac 1671;
168# use base qw/Text::Tradition::Collation::Reading/;
d047cd52 169
170######################################################