use Module::Load;
use Moose;
use Text::Tradition::Collation;
+use Text::Tradition::Stemma;
use Text::Tradition::Witness;
use vars qw( $VERSION );
writer => '_save_collation',
);
-has 'witnesses' => (
- traits => ['Array'],
- isa => 'ArrayRef[Text::Tradition::Witness]',
+has 'witness_hash' => (
+ traits => ['Hash'],
+ isa => 'HashRef[Text::Tradition::Witness]',
handles => {
- witnesses => 'elements',
- add_witness => 'push',
+ witness => 'get',
+ add_witness => 'set',
+ del_witness => 'delete',
+ has_witness => 'exists',
+ witnesses => 'values',
},
- default => sub { [] },
+ default => sub { {} },
);
has 'name' => (
default => 'Tradition',
);
+has 'stemmata' => (
+ traits => ['Array'],
+ isa => 'ArrayRef[Text::Tradition::Stemma]',
+ handles => {
+ all_stemmata => 'elements',
+ _add_stemma => 'push',
+ stemma => 'get',
+ stemma_count => 'count',
+ clear_stemmata => 'clear',
+ },
+ default => sub { [] },
+ );
+
+# Create the witness before trying to add it
around 'add_witness' => sub {
my $orig = shift;
my $self = shift;
# TODO allow add of a Witness object?
my $new_wit = Text::Tradition::Witness->new( @_ );
- $self->$orig( $new_wit );
+ $self->$orig( $new_wit->sigil => $new_wit );
return $new_wit;
};
+# Allow deletion of witness by object as well as by sigil
+around 'del_witness' => sub {
+ my $orig = shift;
+ my $self = shift;
+ my @key_args;
+ foreach my $arg ( @_ ) {
+ push( @key_args,
+ ref( $arg ) eq 'Text::Tradition::Witness' ? $arg->sigil : $arg );
+ }
+ return $self->$orig( @key_args );
+};
+
+# Don't allow an empty hash value
+around 'witness' => sub {
+ my( $orig, $self, $arg ) = @_;
+ return unless $self->has_witness( $arg );
+ return $self->$orig( $arg );
+};
+
=head1 NAME
Text::Tradition - a software model for a set of collated texts
=item * CTE - a TEI XML format produced by Classical Text Editor
+=item * JSON - an alignment table in JSON format, as produced by CollateX and other tools
+
=item * KUL - a specific CSV format for variants, not documented here
=item * TEI - a TEI parallel segmentation format file
Return the Text::Tradition::Witness objects associated with this tradition,
as an array.
+=head2 B<witness>( $sigil )
+
+Returns the Text::Tradition::Witness object whose sigil is $sigil, or undef
+if there is no such object within the tradition.
+
=head2 B<add_witness>( %opts )
Instantiate a new witness with the given options (see documentation for
Text::Tradition::Witness) and add it to the tradition.
+=head2 B<del_witness>( $sigil )
+
+Delete the witness with the given sigil from the tradition. Returns the
+witness object for the deleted witness.
+
=begin testing
use_ok( 'Text::Tradition', "can use module" );
is( $s->name, 'inline', "object has the right name" );
is( scalar $s->witnesses, 3, "object has three witnesses" );
-my $w = $s->add_witness( 'sigil' => 'D' );
-is( ref( $w ), 'Text::Tradition::Witness', "new witness created" );
-is( $w->sigil, 'D', "witness has correct sigil" );
+my $wit_a = $s->witness('A');
+is( ref( $wit_a ), 'Text::Tradition::Witness', "Found a witness A" );
+if( $wit_a ) {
+ is( $wit_a->sigil, 'A', "Witness A has the right sigil" );
+}
+is( $s->witness('X'), undef, "There is no witness X" );
+ok( !exists $s->{'witnesses'}->{'X'}, "Witness key X not created" );
+
+my $wit_d = $s->add_witness( 'sigil' => 'D' );
+is( ref( $wit_d ), 'Text::Tradition::Witness', "new witness created" );
+is( $wit_d->sigil, 'D', "witness has correct sigil" );
is( scalar $s->witnesses, 4, "object now has four witnesses" );
+my $del = $s->del_witness( 'D' );
+is( $del, $wit_d, "Deleted correct witness" );
+is( scalar $s->witnesses, 3, "object has three witnesses again" );
+
# TODO test initialization by witness list when we have it
=end testing
$self->_save_collation( $collation );
# Call the appropriate parser on the given data
- my @format_standalone = qw/ Self CollateX CTE TEI Tabular /;
+ my @format_standalone = qw/ Self CollateText CollateX CTE JSON TEI Tabular /;
my @format_basetext = qw/ KUL /;
my $use_base;
my $format = $init_args->{'input'};
}
}
-=head2 B<witness>( $sigil )
+=head2 add_stemma( $dotfile )
-Returns the Text::Tradition::Witness object whose sigil is $sigil, or undef
-if there is no such object within the tradition.
+Initializes a Text::Tradition::Stemma object from the given dotfile,
+and associates it with the tradition.
=begin testing
use Text::Tradition;
-my $simple = 't/data/simple.txt';
-my $s = Text::Tradition->new(
- 'name' => 'inline',
+my $t = Text::Tradition->new(
+ 'name' => 'simple test',
'input' => 'Tabular',
- 'file' => $simple,
+ 'file' => 't/data/simple.txt',
);
-my $wit_a = $s->witness('A');
-is( ref( $wit_a ), 'Text::Tradition::Witness', "Found a witness A" );
-if( $wit_a ) {
- is( $wit_a->sigil, 'A', "Witness A has the right sigil" );
-}
-is( $s->witness('X'), undef, "There is no witness X" );
+
+is( $t->stemma_count, 0, "No stemmas added yet" );
+my $s;
+ok( $s = $t->add_stemma( dotfile => 't/data/simple.dot' ), "Added a simple stemma" );
+is( ref( $s ), 'Text::Tradition::Stemma', "Got a stemma object returned" );
+is( $t->stemma_count, 1, "Tradition claims to have a stemma" );
+is( $t->stemma(0), $s, "Tradition hands back the right stemma" );
=end testing
=cut
-sub witness {
- my( $self, $sigil ) = @_;
- my $requested_wit;
- foreach my $wit ( $self->witnesses ) {
- if( $wit->sigil eq $sigil ) {
- $requested_wit = $wit;
- last;
- }
- }
- # We depend on an undef return value for no such witness.
- # warn "No such witness $sigil" unless $requested_wit;
- return $requested_wit;
+sub add_stemma {
+ my $self = shift;
+ my %opts = @_;
+ my $stemma_fh;
+ if( $opts{'dotfile'} ) {
+ open $stemma_fh, '<', $opts{'dotfile'}
+ or warn "Could not open file " . $opts{'dotfile'};
+ } elsif( $opts{'dot'} ) {
+ my $str = $opts{'dot'};
+ open $stemma_fh, '<', \$str;
+ }
+ # Assume utf-8
+ binmode $stemma_fh, ':utf8';
+ my $stemma = Text::Tradition::Stemma->new(
+ 'collation' => $self->collation,
+ 'dot' => $stemma_fh );
+ $self->_add_stemma( $stemma ) if $stemma;
+ return $stemma;
}
no Moose;