split off stemma analysis modules from base Tradition layer
Tara L Andrews [Thu, 13 Sep 2012 14:40:17 +0000 (16:40 +0200)]
126 files changed:
.gitignore
MANIFEST.SKIP [deleted file]
analysis/Makefile.PL [new file with mode: 0644]
analysis/lib/Text/Tradition/Analysis.pm [moved from lib/Text/Tradition/Analysis.pm with 97% similarity]
analysis/lib/Text/Tradition/Analysis/Result.pm [moved from lib/Text/Tradition/Analysis/Result.pm with 99% similarity]
analysis/lib/Text/Tradition/HasStemma.pm [new file with mode: 0644]
analysis/lib/Text/Tradition/Stemma.pm [moved from lib/Text/Tradition/Stemma.pm with 99% similarity]
analysis/lib/Text/Tradition/StemmaUtil.pm [moved from lib/Text/Tradition/StemmaUtil.pm with 99% similarity]
analysis/t/00dependencies.t [copied from t/00dependencies.t with 100% similarity]
analysis/t/analysis.t [moved from t/analysis.t with 99% similarity]
analysis/t/data/Collatex-16.xml [copied from t/data/Collatex-16.xml with 100% similarity]
analysis/t/data/analysis.db [moved from t/data/analysis.db with 100% similarity]
analysis/t/data/besoin.dot [moved from t/data/besoin.dot with 100% similarity]
analysis/t/data/besoin.xml [copied from t/data/besoin.xml with 100% similarity]
analysis/t/data/besoin_bad.dot [moved from t/data/besoin_bad.dot with 100% similarity]
analysis/t/data/florilegium.dot [copied from t/data/florilegium.dot with 100% similarity]
analysis/t/data/florilegium_tei_ps.xml [copied from t/data/florilegium_tei_ps.xml with 100% similarity]
analysis/t/data/simple.dot [copied from t/data/simple.dot with 100% similarity]
analysis/t/data/simple.txt [copied from t/data/simple.txt with 100% similarity]
analysis/t/inline2test.conf [copied from t/inline2test.conf with 100% similarity]
analysis/t/stemma.t [moved from t/stemma.t with 82% similarity]
analysis/t/text_tradition_analysis.t [moved from t/text_tradition_analysis.t with 98% similarity]
analysis/t/text_tradition_analysis_result.t [moved from t/text_tradition_analysis_result.t with 99% similarity]
analysis/t/text_tradition_hasstemma.t [new file with mode: 0644]
analysis/t/text_tradition_stemma.t [moved from t/text_tradition_stemma.t with 100% similarity]
base/CHANGES [moved from CHANGES with 100% similarity]
base/MANIFEST.SKIP [new file with mode: 0644]
base/Makefile.PL [moved from Makefile.PL with 96% similarity]
base/TODO [moved from TODO with 100% similarity]
base/doc/graph_format.txt [moved from doc/graph_format.txt with 100% similarity]
base/idp_server/graphcalc.cgi [moved from idp_server/graphcalc.cgi with 100% similarity]
base/idp_server/graphcalc_worker.pl [moved from idp_server/graphcalc_worker.pl with 100% similarity]
base/lib/Text/Tradition.pm [moved from lib/Text/Tradition.pm with 87% similarity]
base/lib/Text/Tradition/Collation.pm [moved from lib/Text/Tradition/Collation.pm with 98% similarity]
base/lib/Text/Tradition/Collation/Data.pm [moved from lib/Text/Tradition/Collation/Data.pm with 100% similarity]
base/lib/Text/Tradition/Collation/Reading.pm [moved from lib/Text/Tradition/Collation/Reading.pm with 100% similarity]
base/lib/Text/Tradition/Collation/Reading/Lexeme.pm [moved from lib/Text/Tradition/Collation/Reading/Lexeme.pm with 100% similarity]
base/lib/Text/Tradition/Collation/Reading/WordForm.pm [moved from lib/Text/Tradition/Collation/Reading/WordForm.pm with 100% similarity]
base/lib/Text/Tradition/Collation/Relationship.pm [moved from lib/Text/Tradition/Collation/Relationship.pm with 100% similarity]
base/lib/Text/Tradition/Collation/RelationshipStore.pm [moved from lib/Text/Tradition/Collation/RelationshipStore.pm with 100% similarity]
base/lib/Text/Tradition/Directory.pm [moved from lib/Text/Tradition/Directory.pm with 90% similarity]
base/lib/Text/Tradition/Error.pm [moved from lib/Text/Tradition/Error.pm with 100% similarity]
base/lib/Text/Tradition/Language/Armenian.pm [moved from lib/Text/Tradition/Language/Armenian.pm with 100% similarity]
base/lib/Text/Tradition/Language/Base.pm [moved from lib/Text/Tradition/Language/Base.pm with 100% similarity]
base/lib/Text/Tradition/Language/English.pm [moved from lib/Text/Tradition/Language/English.pm with 100% similarity]
base/lib/Text/Tradition/Language/French.pm [moved from lib/Text/Tradition/Language/French.pm with 100% similarity]
base/lib/Text/Tradition/Language/Greek.pm [moved from lib/Text/Tradition/Language/Greek.pm with 100% similarity]
base/lib/Text/Tradition/Language/Latin.pm [moved from lib/Text/Tradition/Language/Latin.pm with 100% similarity]
base/lib/Text/Tradition/Language/Perseus.pm [moved from lib/Text/Tradition/Language/Perseus.pm with 100% similarity]
base/lib/Text/Tradition/Parser/BaseText.pm [moved from lib/Text/Tradition/Parser/BaseText.pm with 100% similarity]
base/lib/Text/Tradition/Parser/CTE.pm [moved from lib/Text/Tradition/Parser/CTE.pm with 100% similarity]
base/lib/Text/Tradition/Parser/CollateText.pm [moved from lib/Text/Tradition/Parser/CollateText.pm with 100% similarity]
base/lib/Text/Tradition/Parser/CollateX.pm [moved from lib/Text/Tradition/Parser/CollateX.pm with 100% similarity]
base/lib/Text/Tradition/Parser/GraphML.pm [moved from lib/Text/Tradition/Parser/GraphML.pm with 100% similarity]
base/lib/Text/Tradition/Parser/JSON.pm [moved from lib/Text/Tradition/Parser/JSON.pm with 100% similarity]
base/lib/Text/Tradition/Parser/KUL.pm [moved from lib/Text/Tradition/Parser/KUL.pm with 100% similarity]
base/lib/Text/Tradition/Parser/Self.pm [moved from lib/Text/Tradition/Parser/Self.pm with 89% similarity]
base/lib/Text/Tradition/Parser/TEI.pm [moved from lib/Text/Tradition/Parser/TEI.pm with 100% similarity]
base/lib/Text/Tradition/Parser/Tabular.pm [moved from lib/Text/Tradition/Parser/Tabular.pm with 100% similarity]
base/lib/Text/Tradition/Parser/Util.pm [moved from lib/Text/Tradition/Parser/Util.pm with 100% similarity]
base/lib/Text/Tradition/Store.pm [moved from lib/Text/Tradition/Store.pm with 100% similarity]
base/lib/Text/Tradition/TypeMap/Entry.pm [moved from lib/Text/Tradition/TypeMap/Entry.pm with 100% similarity]
base/lib/Text/Tradition/User.pm [moved from lib/Text/Tradition/User.pm with 100% similarity]
base/lib/Text/Tradition/UserStore.pm [moved from lib/Text/Tradition/UserStore.pm with 100% similarity]
base/lib/Text/Tradition/Witness.pm [moved from lib/Text/Tradition/Witness.pm with 100% similarity]
base/script/admin_users.pl [moved from script/admin_users.pl with 100% similarity]
base/script/analyze.pl [moved from script/analyze.pl with 100% similarity]
base/script/dblookup.pl [moved from script/dblookup.pl with 100% similarity]
base/script/group_vars.pl [moved from script/group_vars.pl with 100% similarity]
base/script/join_readings.pl [moved from script/join_readings.pl with 100% similarity]
base/script/majority_text.pl [moved from script/majority_text.pl with 100% similarity]
base/script/make_tradition.pl [moved from script/make_tradition.pl with 100% similarity]
base/script/maketestdb.sh [moved from script/maketestdb.sh with 100% similarity]
base/script/orth_case_links.pl [moved from script/orth_case_links.pl with 100% similarity]
base/script/poslink.pl [moved from script/poslink.pl with 100% similarity]
base/script/propagate_transitive.pl [moved from script/propagate_transitive.pl with 100% similarity]
base/script/statistics.pl [moved from script/statistics.pl with 100% similarity]
base/script/strip_punctuation.pl [moved from script/strip_punctuation.pl with 100% similarity]
base/t/00dependencies.t [moved from t/00dependencies.t with 100% similarity]
base/t/01app.t [moved from t/01app.t with 100% similarity]
base/t/02pod.t [moved from t/02pod.t with 100% similarity]
base/t/03podcoverage.t [moved from t/03podcoverage.t with 100% similarity]
base/t/bin/make-load-test.pl [moved from t/bin/make-load-test.pl with 100% similarity]
base/t/bin/update-load-test.pl [moved from t/bin/update-load-test.pl with 100% similarity]
base/t/data/Collatex-16.xml [moved from t/data/Collatex-16.xml with 100% similarity]
base/t/data/armexample.xls [moved from t/data/armexample.xls with 100% similarity]
base/t/data/armexample.xlsx [moved from t/data/armexample.xlsx with 100% similarity]
base/t/data/besoin.xml [moved from t/data/besoin.xml with 100% similarity]
base/t/data/cx16.json [moved from t/data/cx16.json with 100% similarity]
base/t/data/florilegium.csv [moved from t/data/florilegium.csv with 100% similarity]
base/t/data/florilegium.dot [moved from t/data/florilegium.dot with 100% similarity]
base/t/data/florilegium_graphml.xml [moved from t/data/florilegium_graphml.xml with 100% similarity]
base/t/data/florilegium_tei_cte.xml [moved from t/data/florilegium_tei_cte.xml with 100% similarity]
base/t/data/florilegium_tei_ps.xml [moved from t/data/florilegium_tei_ps.xml with 100% similarity]
base/t/data/john.xml [moved from t/data/john.xml with 100% similarity]
base/t/data/legendfrag.xml [moved from t/data/legendfrag.xml with 100% similarity]
base/t/data/lexformat.xml [moved from t/data/lexformat.xml with 100% similarity]
base/t/data/lf2.xml [moved from t/data/lf2.xml with 100% similarity]
base/t/data/load-save-benchmark.json [moved from t/data/load-save-benchmark.json with 100% similarity]
base/t/data/simple.dot [moved from t/data/simple.dot with 100% similarity]
base/t/data/simple.txt [moved from t/data/simple.txt with 100% similarity]
base/t/data/speed_test_load.sql [moved from t/data/speed_test_load.sql with 100% similarity]
base/t/data/witnesses/group.xml [moved from t/data/witnesses/group.xml with 100% similarity]
base/t/data/witnesses/teiwit.xml [moved from t/data/witnesses/teiwit.xml with 100% similarity]
base/t/data/witnesses/testwit.json [moved from t/data/witnesses/testwit.json with 100% similarity]
base/t/graph.t [moved from t/graph.t with 100% similarity]
base/t/inline2test.conf [moved from t/inline2test.conf with 100% similarity]
base/t/lexeme_serialize.t [moved from t/lexeme_serialize.t with 85% similarity]
base/t/load-save-speed.t [moved from t/load-save-speed.t with 98% similarity]
base/t/text_tradition.t [moved from t/text_tradition.t with 74% similarity]
base/t/text_tradition_collation.t [moved from t/text_tradition_collation.t with 91% similarity]
base/t/text_tradition_collation_relationshipstore.t [moved from t/text_tradition_collation_relationshipstore.t with 100% similarity]
base/t/text_tradition_directory.t [moved from t/text_tradition_directory.t with 55% similarity]
base/t/text_tradition_language_armenian.t [moved from t/text_tradition_language_armenian.t with 100% similarity]
base/t/text_tradition_language_english.t [moved from t/text_tradition_language_english.t with 100% similarity]
base/t/text_tradition_language_french.t [moved from t/text_tradition_language_french.t with 100% similarity]
base/t/text_tradition_language_greek.t [moved from t/text_tradition_language_greek.t with 100% similarity]
base/t/text_tradition_language_latin.t [moved from t/text_tradition_language_latin.t with 100% similarity]
base/t/text_tradition_parser_collatex.t [moved from t/text_tradition_parser_collatex.t with 100% similarity]
base/t/text_tradition_parser_json.t [moved from t/text_tradition_parser_json.t with 100% similarity]
base/t/text_tradition_parser_self.t [moved from t/text_tradition_parser_self.t with 74% similarity]
base/t/text_tradition_parser_tabular.t [moved from t/text_tradition_parser_tabular.t with 100% similarity]
base/t/text_tradition_parser_tei.t [moved from t/text_tradition_parser_tei.t with 100% similarity]
base/t/text_tradition_user.t [moved from t/text_tradition_user.t with 100% similarity]
base/t/text_tradition_user_collapse.t [moved from t/text_tradition_user_collapse.t with 100% similarity]
base/t/text_tradition_witness.t [moved from t/text_tradition_witness.t with 100% similarity]

index 484a79c..b00040d 100644 (file)
@@ -1,11 +1,22 @@
 *~
-*.bbprojectd/
-t/var
+*/t/var
 data
-!/t/data
+!*/t/data
 Makefile
 Makefile.old
 META.yml
 blib
 db
 inc
+blib/
+.build/
+_build/
+cover_db/
+inc/
+Build
+Build.bat
+.last_cover_stats
+MANIFEST.bak
+MYMETA.yml
+nytprof.out
+pm_to_blib
diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP
deleted file mode 100644 (file)
index 441a8fe..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-lib/Text/Tradition/Parser/BaseText.pm
-lib/Text/Tradition/Parser/CollateText.pm
-lib/Text/Tradition/Parser/CTE.pm
-lib/Text/Tradition/Parser/KUL.pm
-lib/Text/Tradition/Analysis.pm
-lib/Text/Tradition/Analysis/Result.pm
-t/analysis.t
-t/text_tradition_analysis.t
-t/text_tradition_analysis_result.t
-.git/
-.gitignore
diff --git a/analysis/Makefile.PL b/analysis/Makefile.PL
new file mode 100644 (file)
index 0000000..62d8e49
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+
+use inc::Module::Install;
+author( 'Tara L Andrews <aurum@cpan.org>' );
+license( 'perl' );
+perl_version( '5.012' );
+all_from( 'lib/Text/Tradition/Analysis.pm' );
+requires( 'Algorithm::Diff' );
+requires( 'Bio::Phylo::IO' );
+requires( 'File::chdir' );
+requires( 'File::Which' );
+requires( 'Graph' );
+requires( 'Graph::Reader::Dot' );
+requires( 'IPC::Run' );
+requires( 'JSON' );
+requires( 'LWP::UserAgent' );
+requires( 'Moose' );
+requires( 'Moose::Role' );
+requires( 'Set::Scalar' );
+requires( 'Text::Tradition' );
+requires( 'Text::Tradition::Directory' );
+requires( 'Text::Tradition::Error' );
+requires( 'TryCatch' );
+
+build_requires( 'Test::More::UTF8' );
+&WriteAll;
similarity index 97%
rename from lib/Text/Tradition/Analysis.pm
rename to analysis/lib/Text/Tradition/Analysis.pm
index e1a69cd..3b76ca1 100644 (file)
@@ -14,8 +14,10 @@ use Text::Tradition::Directory;
 use Text::Tradition::Stemma;
 use TryCatch;
 
-use vars qw/ @EXPORT_OK /;
+use vars qw/ @EXPORT_OK $VERSION /;
 @EXPORT_OK = qw/ run_analysis group_variants analyze_variant_location wit_stringify /;
+$VERSION = "1.0";
+
 
 my $SOLVER_URL = 'http://byzantini.st/cgi-bin/graphcalc.cgi';
 my $unsolved_problems = {};
@@ -32,6 +34,7 @@ Text::Tradition::Analysis - functions for stemma analysis of a tradition
     'name' => 'this is a text',
     'input' => 'TEI',
     'file' => '/path/to/tei_parallel_seg_file.xml' );
+  $t->enable_stemmata;
   $t->add_stemma( 'dotfile' => $stemmafile );
 
   my $variant_data = run_analysis( $tradition );
@@ -41,9 +44,18 @@ Text::Tradition::Analysis - functions for stemma analysis of a tradition
 =head1 DESCRIPTION
 
 Text::Tradition is a library for representation and analysis of collated
-texts, particularly medieval ones.  The Collation is the central feature of
-a Tradition, where the text, its sequence of readings, and its relationships
-between readings are actually kept.
+texts, particularly medieval ones.  Where the Collation is the central feature of
+a Tradition, it may also have one or more temmata associated with it, and these stemmata may be analyzed. This package provides the following modules:
+
+=over 4
+
+=item * L<Text::Tradition::HasStemma> - a role that can be composed into Text::Tradition objects, providing the ability for Text::Tradition::Stemma objects to be associated with them.
+
+=item * L<Text::Tradition::Stemma> - an object class that represents stemma hypotheses, both rooted (with a single archetype) and unrooted (e.g. phylogenetic trees).
+
+=item * Text::Tradition::Analysis (this package). Provides functions for the analysis of a given stemma against the collation within a given Tradition.
+
+=back
 
 =head1 SUBROUTINES
 
@@ -75,6 +87,7 @@ my $datafile = 't/data/florilegium_tei_ps.xml';
 my $tradition = Text::Tradition->new( 'input' => 'TEI',
                                       'name' => 'test0',
                                       'file' => $datafile );
+$tradition->enable_stemmata;
 my $s = $tradition->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
 is( ref( $s ), 'Text::Tradition::Stemma', "Added stemma to tradition" );
 
similarity index 99%
rename from lib/Text/Tradition/Analysis/Result.pm
rename to analysis/lib/Text/Tradition/Analysis/Result.pm
index da1e123..2e920ff 100644 (file)
@@ -88,6 +88,7 @@ my $datafile = 't/data/florilegium_tei_ps.xml';
 my $tradition = Text::Tradition->new( 'input' => 'TEI',
                                       'name' => 'flortest',
                                       'file' => $datafile );
+$tradition->enable_stemmata;
 my $s = $tradition->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
 
 my $sets = [ [ qw/ D Q / ], [ qw/ F H / ], [ qw/ A B C P S T / ] ];
diff --git a/analysis/lib/Text/Tradition/HasStemma.pm b/analysis/lib/Text/Tradition/HasStemma.pm
new file mode 100644 (file)
index 0000000..c797fab
--- /dev/null
@@ -0,0 +1,105 @@
+package Text::Tradition::HasStemma;
+
+use strict;
+use warnings;
+use Moose::Role;
+use Text::Tradition::Stemma;
+
+=head1 NAME
+
+Text::Tradition::HasStemma - add-on to associate stemma hypotheses to Text::Tradition objects
+
+=head1 DESCRIPTION
+
+It is often the case that, for a given text tradition, the order of copying of the witnesses can or should be reconstructed (or at least the attempt should be made.) This class is a role that can be applied to Text::Tradition objects to record stemma hypotheses.  See the documentation for L<Text::Tradition::Stemma> for more information.
+
+=head1 METHODS
+
+=head2 stemmata
+
+Return a list of all stemmata associated with the tradition.
+
+=head2 stemma_count
+
+Return the number of stemma hypotheses defined for this tradition.
+
+=head2 stemma( $idx )
+
+Return the L<Text::Tradition::Stemma> object identified by the given index.
+
+=head2 clear_stemmata
+
+Delete all stemma hypotheses associated with this tradition.
+
+=cut
+
+has 'stemmata' => (
+       traits => ['Array'],
+       isa => 'ArrayRef[Text::Tradition::Stemma]',
+       handles => {
+               stemmata => 'elements',
+               _add_stemma => 'push',
+               stemma => 'get',
+               stemma_count => 'count',
+               clear_stemmata => 'clear',
+       },
+       default => sub { [] },
+       );
+  
+
+=head2 add_stemma( $dotfile )
+
+Initializes a Text::Tradition::Stemma object from the given dotfile,
+and associates it with the tradition.
+
+=begin testing
+
+use Text::Tradition;
+
+my $t = Text::Tradition->new( 
+    'name'  => 'simple test', 
+    'input' => 'Tabular',
+    'file'  => 't/data/simple.txt',
+    );
+$t->enable_stemmata;
+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 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( 
+               'dot' => $stemma_fh );
+       $self->_add_stemma( $stemma ) if $stemma;
+       return $stemma;
+}
+
+1;
+
+=head1 LICENSE
+
+This package is free software and is provided "as is" without express
+or implied warranty.  You can redistribute it and/or modify it under
+the same terms as Perl itself.
+
+=head1 AUTHOR
+
+Tara L Andrews E<lt>aurum@cpan.orgE<gt>
similarity index 99%
rename from lib/Text/Tradition/Stemma.pm
rename to analysis/lib/Text/Tradition/Stemma.pm
index 765547e..b88226b 100644 (file)
@@ -1,6 +1,5 @@
 package Text::Tradition::Stemma;
 
-use Bio::Phylo::IO;
 use Encode qw( decode_utf8 );
 use File::Temp;
 use Graph;
similarity index 99%
rename from lib/Text/Tradition/StemmaUtil.pm
rename to analysis/lib/Text/Tradition/StemmaUtil.pm
index 5c3f848..1aba28b 100644 (file)
@@ -10,7 +10,6 @@ use File::chdir;
 use File::Temp;
 use File::Which;
 use Graph;
-use Graph::Reader::Dot;
 use IPC::Run qw/ run binary /;
 use Text::Tradition::Error;
 use Text::Tradition::Stemma;
similarity index 99%
rename from t/analysis.t
rename to analysis/t/analysis.t
index bc5661f..08ac38f 100755 (executable)
@@ -15,6 +15,7 @@ eval { no warnings; binmode $DB::OUT, ':utf8'; $DB::deep = 1000 };
 my $tradition = Text::Tradition->new(
        'input' => 'Self',
        'file' => 't/data/besoin.xml' );
+$tradition->enable_stemmata;
 $tradition->add_stemma( 'dotfile' => 't/data/besoin.dot' );
 
 # Run the analysis of the tradition
similarity index 100%
rename from t/data/besoin.dot
rename to analysis/t/data/besoin.dot
similarity index 82%
rename from t/stemma.t
rename to analysis/t/stemma.t
index 84193a9..094c30b 100644 (file)
@@ -6,8 +6,7 @@ use Test::More;
 use lib 'lib';
 use Text::Tradition;
 use Text::Tradition::StemmaUtil qw/ character_input phylip_pars parse_newick /;
-use XML::LibXML;
-use XML::LibXML::XPathContext;
+use TryCatch;
 
 my $datafile = 't/data/Collatex-16.xml'; #TODO need other test data
 
@@ -23,6 +22,7 @@ $c->add_relationship( 'n9', 'n10', { 'type' => 'spelling' } );
 $c->add_relationship( 'n12', 'n13', { 'type' => 'spelling' } );
 $c->calculate_ranks();
 
+$tradition->enable_stemmata;
 my $stemma = $tradition->add_stemma( dotfile => 't/data/simple.dot' );
 
 # Test for object creation
@@ -51,16 +51,16 @@ foreach my $ml ( @mlines ) {
 
 # Test that pars runs
 SKIP: {
-    skip "pars not in path", 3 unless File::Which::which('pars');
-    my $newick = phylip_pars( $mstr );
-    ok( $newick, "pars ran successfully" );
+       skip "pars not in path", 3 unless File::Which::which('pars');
+       my $newick = phylip_pars( $mstr );
+       ok( $newick, "pars ran successfully" );
 
        my $trees = parse_newick( $newick );
-    # Test that we get a tree
-    is( scalar @$trees, 1, "Got a single tree" );
-    # Test that the tree has all our witnesses
-    my $tree = $trees->[0];
-    is( scalar $tree->witnesses, 3, "All witnesses in the tree" );
+       # Test that we get a tree
+       is( scalar @$trees, 1, "Got a single tree" );
+       # Test that the tree has all our witnesses
+       my $tree = $trees->[0];
+       is( scalar $tree->witnesses, 3, "All witnesses in the tree" );
 }
 
 # Test our dot output
@@ -71,5 +71,4 @@ ok( $display !~ /hypothetical/, "Graph is display rather than edit" );
 my $editable = $stemma->editable();
 ok( $editable =~ /digraph/, "Got a dot edit graph" );
 ok( $editable =~ /hypothetical/, "Graph contains an edit class" );
-
 done_testing();
similarity index 98%
rename from t/text_tradition_analysis.t
rename to analysis/t/text_tradition_analysis.t
index f568b36..1ebf655 100644 (file)
@@ -15,6 +15,7 @@ my $datafile = 't/data/florilegium_tei_ps.xml';
 my $tradition = Text::Tradition->new( 'input' => 'TEI',
                                       'name' => 'test0',
                                       'file' => $datafile );
+$tradition->enable_stemmata;
 my $s = $tradition->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
 is( ref( $s ), 'Text::Tradition::Stemma', "Added stemma to tradition" );
 
similarity index 99%
rename from t/text_tradition_analysis_result.t
rename to analysis/t/text_tradition_analysis_result.t
index e3462dc..2997818 100644 (file)
@@ -20,6 +20,7 @@ my $datafile = 't/data/florilegium_tei_ps.xml';
 my $tradition = Text::Tradition->new( 'input' => 'TEI',
                                       'name' => 'flortest',
                                       'file' => $datafile );
+$tradition->enable_stemmata;
 my $s = $tradition->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
 
 my $sets = [ [ qw/ D Q / ], [ qw/ F H / ], [ qw/ A B C P S T / ] ];
diff --git a/analysis/t/text_tradition_hasstemma.t b/analysis/t/text_tradition_hasstemma.t
new file mode 100644 (file)
index 0000000..ecf253e
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Test::More 'no_plan';
+$| = 1;
+
+
+
+# =begin testing
+{
+use Text::Tradition;
+
+my $t = Text::Tradition->new( 
+    'name'  => 'simple test', 
+    'input' => 'Tabular',
+    'file'  => 't/data/simple.txt',
+    );
+$t->enable_stemmata;
+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" );
+}
+
+
+
+
+1;
similarity index 100%
rename from CHANGES
rename to base/CHANGES
diff --git a/base/MANIFEST.SKIP b/base/MANIFEST.SKIP
new file mode 100644 (file)
index 0000000..3b31671
--- /dev/null
@@ -0,0 +1,5 @@
+lib/Text/Tradition/Parser/BaseText.pm
+lib/Text/Tradition/Parser/CollateText.pm
+lib/Text/Tradition/Parser/KUL.pm
+.git/
+.gitignore
similarity index 96%
rename from Makefile.PL
rename to base/Makefile.PL
index 3aa72f4..c85aaa5 100644 (file)
@@ -23,7 +23,9 @@ requires( 'KiokuX::Model' );
 requires( 'KiokuX::User::Util' );
 requires( 'Module::Load' );
 requires( 'Moose' );
+requires( 'Moose::Util' );
 requires( 'Moose::Util::TypeConstraints' );
+requires( 'Safe::Isa' );
 requires( 'Spreadsheet::ParseExcel' );
 requires( 'Spreadsheet::XLSX' );
 requires( 'StackTrace::Auto' );
diff --git a/TODO b/base/TODO
similarity index 100%
rename from TODO
rename to base/TODO
similarity index 87%
rename from lib/Text/Tradition.pm
rename to base/lib/Text/Tradition.pm
index 41e14cc..51258dc 100644 (file)
@@ -3,10 +3,12 @@ package Text::Tradition;
 use JSON qw / from_json /;
 use Module::Load;
 use Moose;
+use Moose::Util qw/ does_role apply_all_roles /;
 use Text::Tradition::Collation;
-use Text::Tradition::Stemma;
+use Text::Tradition::Error;
 use Text::Tradition::Witness;
 use Text::Tradition::User;
+use TryCatch;
 
 use vars qw( $VERSION );
 $VERSION = "0.5";
@@ -42,19 +44,6 @@ has 'language' => (
        predicate => 'has_language',
        );
     
-has 'stemmata' => (
-       traits => ['Array'],
-       isa => 'ArrayRef[Text::Tradition::Stemma]',
-       handles => {
-               stemmata => 'elements',
-               _add_stemma => 'push',
-               stemma => 'get',
-               stemma_count => 'count',
-               clear_stemmata => 'clear',
-       },
-       default => sub { [] },
-       );
-  
 has '_initialized' => (
        is => 'ro',
        isa => 'Bool',
@@ -335,49 +324,25 @@ sub add_json_witnesses {
        }
 }
 
-=head2 add_stemma( $dotfile )
-
-Initializes a Text::Tradition::Stemma object from the given dotfile,
-and associates it with the tradition.
-
-=begin testing
-
-use Text::Tradition;
+=head1 PLUGIN HOOKS
 
-my $t = Text::Tradition->new( 
-    'name'  => 'simple test', 
-    'input' => 'Tabular',
-    'file'  => 't/data/simple.txt',
-    );
-
-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" );
+=head2 enable_stemmata();
 
-=end testing
+If the tradition in question does not have the HasStemma role, make it so. Throws
+an error if the role (ergo, if the Analysis package) is not installed.
 
 =cut
 
-sub add_stemma {
+sub enable_stemmata {
        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;
+       my $rolename = 'Text::Tradition::HasStemma';
+       return 1 if does_role( $self, $rolename );
+       try {
+               apply_all_roles( $self, $rolename );
+       } catch {
+               throw( "Cannot apply role to enable stemmata; is the Analysis extension installed?" );
        }
-       # Assume utf-8
-       binmode $stemma_fh, ':utf8';
-       my $stemma = Text::Tradition::Stemma->new( 
-               'dot' => $stemma_fh );
-       $self->_add_stemma( $stemma ) if $stemma;
-       return $stemma;
+       return 1;
 }
 
 sub lemmatize {
@@ -391,6 +356,13 @@ sub lemmatize {
        $mod->can( 'lemmatize' )->( $self );
 }
 
+sub throw {
+       Text::Tradition::Error->throw( 
+               'ident' => 'Tradition error',
+               'message' => $_[0],
+               );
+}
+
 no Moose;
 __PACKAGE__->meta->make_immutable;
 
similarity index 98%
rename from lib/Text/Tradition/Collation.pm
rename to base/lib/Text/Tradition/Collation.pm
index 022c2bc..d652850 100644 (file)
@@ -897,6 +897,7 @@ readings.  This is the native transfer format for a tradition.
 =begin testing
 
 use Text::Tradition;
+use TryCatch;
 
 my $READINGS = 311;
 my $PATHS = 361;
@@ -930,11 +931,20 @@ is( scalar $st->collation->paths, $PATHS, "Reparsed collation has all paths" );
 is( scalar $st->collation->relationships, 3, "Reparsed collation has new relationships" );
 
 # Now add a stemma, write to GraphML, and look at the output.
-my $stemma = $tradition->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
-is( ref( $stemma ), 'Text::Tradition::Stemma', "Parsed dotfile into stemma" );
-is( $tradition->stemmata, 1, "Tradition now has the stemma" );
-$graphml = $c->as_graphml;
-like( $graphml, qr/digraph/, "Digraph declaration exists in GraphML" );
+my $SKIP_STEMMA;
+try {
+       $tradition->enable_stemmata;
+} catch {
+       $SKIP_STEMMA = 1;
+}
+SKIP: {
+       skip "Analysis module not present", 3 if $SKIP_STEMMA;
+       my $stemma = $tradition->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
+       is( ref( $stemma ), 'Text::Tradition::Stemma', "Parsed dotfile into stemma" );
+       is( $tradition->stemmata, 1, "Tradition now has the stemma" );
+       $graphml = $c->as_graphml;
+       like( $graphml, qr/digraph/, "Digraph declaration exists in GraphML" );
+}
 
 # Now add a user, write to GraphML, and look at the output.
 unlike( $graphml, qr/testuser/, "Test user name does not exist in GraphML yet" );
@@ -950,6 +960,7 @@ like( $graphml, qr/testuser/, "Test user name now exists in GraphML" );
 
 =cut
 
+## TODO MOVE this to Tradition.pm
 sub as_graphml {
     my( $self, $options ) = @_;
        $self->calculate_ranks unless $self->_graphcalc_done;
@@ -1013,12 +1024,15 @@ sub as_graphml {
        }
     # Extra custom keys for complex objects that should be saved in some form.
     # The subroutine should return a string, or undef/empty.
-    $graph_attributes{'stemmata'} = sub { 
-       my @stemstrs;
-               map { push( @stemstrs, $_->editable( {linesep => ''} ) ) } 
-                       $self->tradition->stemmata;
-               join( "\n", @stemstrs );
-       };
+    if( $tmeta->has_method('stemmata') ) {
+               $graph_attributes{'stemmata'} = sub { 
+                       my @stemstrs;
+                       map { push( @stemstrs, $_->editable( {linesep => ''} ) ) } 
+                               $self->tradition->stemmata;
+                       join( "\n", @stemstrs );
+               };
+       }
+       
     $graph_attributes{'user'} = sub { 
        $self->tradition->user ? $self->tradition->user->id : undef 
     };
similarity index 90%
rename from lib/Text/Tradition/Directory.pm
rename to base/lib/Text/Tradition/Directory.pm
index 0734168..542ad4d 100644 (file)
@@ -8,6 +8,7 @@ use Encode qw/ decode_utf8 /;
 use KiokuDB::GC::Naive;
 use KiokuDB::TypeMap;
 use KiokuDB::TypeMap::Entry::Naive;
+use Safe::Isa;
 use Text::Tradition::Error;
 
 ## users
@@ -31,6 +32,7 @@ Text::Tradition::Directory - a KiokuDB interface for storing and retrieving trad
   );
   
   my $tradition = Text::Tradition->new( @args );
+  $tradition->enable_stemmata;
   my $stemma = $tradition->add_stemma( dotfile => $dotfile ); 
   $d->save_tradition( $tradition );
   
@@ -95,6 +97,7 @@ WARNING!! Garbage collection does not yet work. Use this sparingly.
 
 use TryCatch;
 use File::Temp;
+use Safe::Isa;
 use Text::Tradition;
 use_ok 'Text::Tradition::Directory';
 
@@ -108,26 +111,31 @@ my $t = Text::Tradition->new(
        'input' => 'Tabular',
        'file'  => 't/data/simple.txt',
        );
+my $stemma_enabled;
+eval { $stemma_enabled = $t->enable_stemmata; };
 
 {
        my $d = Text::Tradition::Directory->new( 'dsn' => $dsn,
                'extra_args' => { 'create' => 1 } );
-       is( ref $d, 'Text::Tradition::Directory', "Got directory object" );
+       ok( $d->$_isa('Text::Tradition::Directory'), "Got directory object" );
        
        my $scope = $d->new_scope;
        $uuid = $d->save( $t );
        ok( $uuid, "Saved test tradition" );
        
-       my $s = $t->add_stemma( dotfile => 't/data/simple.dot' );
-       ok( $d->save( $t ), "Updated tradition with stemma" );
-       is( $d->tradition( $uuid ), $t, "Correct tradition returned for id" );
-       is( $d->tradition( $uuid )->stemma(0), $s, "...and it has the correct stemma" );
-       try {
-               $d->save( $s );
-       } catch( Text::Tradition::Error $e ) {
-               is( $e->ident, 'database error', "Got exception trying to save stemma directly" );
-               like( $e->message, qr/Cannot directly save non-Tradition object/, 
-                       "Exception has correct message" );
+       SKIP: {
+               skip "Analysis package not installed", 5 unless $stemma_enabled;
+               my $s = $t->add_stemma( dotfile => 't/data/simple.dot' );
+               ok( $d->save( $t ), "Updated tradition with stemma" );
+               is( $d->tradition( $uuid ), $t, "Correct tradition returned for id" );
+               is( $d->tradition( $uuid )->stemma(0), $s, "...and it has the correct stemma" );
+               try {
+                       $d->save( $s );
+               } catch( Text::Tradition::Error $e ) {
+                       is( $e->ident, 'database error', "Got exception trying to save stemma directly" );
+                       like( $e->message, qr/Cannot directly save non-Tradition object/, 
+                               "Exception has correct message" );
+               }
        }
 }
 my $nt = Text::Tradition->new(
@@ -135,7 +143,7 @@ my $nt = Text::Tradition->new(
        'input' => 'CollateX',
        'file' => 't/data/Collatex-16.xml',
        );
-is( ref( $nt ), 'Text::Tradition', "Made new tradition" );
+ok( $nt->$_isa('Text::Tradition'), "Made new tradition" );
 
 {
        my $f = Text::Tradition::Directory->new( 'dsn' => $dsn );
@@ -149,24 +157,28 @@ is( ref( $nt ), 'Text::Tradition', "Made new tradition" );
        my( $tlobj ) = grep { $_->{'id'} eq $uuid } @tlist;
        is( $tlobj->{'name'}, $tf->name, "Directory index has correct tradition name" );
        is( $tf->name, $t->name, "Retrieved the tradition from a new directory" );
-       my $sid = $f->object_to_id( $tf->stemma(0) );
-       try {
-               $f->tradition( $sid );
-       } catch( Text::Tradition::Error $e ) {
-               is( $e->ident, 'database error', "Got exception trying to fetch stemma directly" );
-               like( $e->message, qr/not a Text::Tradition/, "Exception has correct message" );
-       }
-       try {
-               $f->delete( $sid );
-       } catch( Text::Tradition::Error $e ) {
-               is( $e->ident, 'database error', "Got exception trying to delete stemma directly" );
-               like( $e->message, qr/Cannot directly delete non-Tradition object/, 
-                       "Exception has correct message" );
+       my $sid;
+       SKIP: {
+               skip "Analysis package not installed", 4 unless $stemma_enabled;
+               $sid = $f->object_to_id( $tf->stemma(0) );
+               try {
+                       $f->tradition( $sid );
+               } catch( Text::Tradition::Error $e ) {
+                       is( $e->ident, 'database error', "Got exception trying to fetch stemma directly" );
+                       like( $e->message, qr/not a Text::Tradition/, "Exception has correct message" );
+               }
+               try {
+                       $f->delete( $sid );
+               } catch( Text::Tradition::Error $e ) {
+                       is( $e->ident, 'database error', "Got exception trying to delete stemma directly" );
+                       like( $e->message, qr/Cannot directly delete non-Tradition object/, 
+                               "Exception has correct message" );
+               }
        }
        
        $f->delete( $uuid );
        ok( !$f->exists( $uuid ), "Object is deleted from DB" );
-       ok( !$f->exists( $sid ), "Object stemma also deleted from DB" );
+       ok( !$f->exists( $sid ), "Object stemma also deleted from DB" ) if $stemma_enabled;
        is( scalar $f->traditionlist, 1, "Object is deleted from index" );
 }
 
@@ -256,12 +268,12 @@ before [ qw/ delete / ] => sub {
        my $self = shift;
        my @nontrad;
        foreach my $obj ( @_ ) {
-               if( ref( $obj ) && ref( $obj ) ne 'Text::Tradition'
-            && ref ($obj) ne 'Text::Tradition::User' ) {
+               if( ref( $obj ) && !$obj->$_isa( 'Text::Tradition' )
+            && !$obj->$_isa('Text::Tradition::User') ) {
                        # Is it an id => Tradition hash?
                        if( ref( $obj ) eq 'HASH' && keys( %$obj ) == 1 ) {
                                my( $k ) = keys %$obj;
-                               next if ref( $obj->{$k} ) eq 'Text::Tradition';
+                               next if $obj->{$k}->$_isa('Text::Tradition');
                        }
                        push( @nontrad, $obj );
                }
@@ -297,7 +309,7 @@ sub tradition {
                        }
                }
        }
-       if( $obj && ref( $obj ) ne 'Text::Tradition' ) {
+       if( $obj && !$obj->$_isa('Text::Tradition') ) {
                throw( "Retrieved object is a " . ref( $obj ) . ", not a Text::Tradition" );
        }
        return $obj;
similarity index 89%
rename from lib/Text/Tradition/Parser/Self.pm
rename to base/lib/Text/Tradition/Parser/Self.pm
index 981a855..255f804 100644 (file)
@@ -97,8 +97,10 @@ source of the XML to be parsed.
 =begin testing
 
 use File::Temp;
+use Safe::Isa;
 use Test::Warn;
 use Text::Tradition;
+use TryCatch;
 binmode STDOUT, ":utf8";
 binmode STDERR, ":utf8";
 eval { no warnings; binmode $DB::OUT, ":utf8"; };
@@ -110,7 +112,7 @@ my $t = Text::Tradition->new(
     'file'  => $tradition,
     );
 
-is( ref( $t ), 'Text::Tradition', "Parsed GraphML version 2" );
+ok( $t->$_isa('Text::Tradition'), "Parsed GraphML version 2" );
 if( $t ) {
     is( scalar $t->collation->readings, 319, "Collation has all readings" );
     is( scalar $t->collation->paths, 376, "Collation has all paths" );
@@ -120,7 +122,15 @@ if( $t ) {
 # TODO add a relationship, add a stemma, write graphml, reparse it, check that 
 # the new data is there
 $t->language('Greek');
-$t->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
+my $stemma_enabled;
+try {
+       $stemma_enabled = $t->enable_stemmata;
+} catch {
+       ok( 1, "Skipping stemma tests without Analysis module" );
+}
+if( $stemma_enabled ) {
+       $t->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
+}
 $t->collation->add_relationship( 'w12', 'w13', 
        { 'type' => 'grammatical', 'scope' => 'global', 
          'annotation' => 'This is some note' } );
@@ -128,7 +138,7 @@ ok( $t->collation->get_relationship( 'w12', 'w13' ), "Relationship set" );
 my $graphml_str = $t->collation->as_graphml;
 
 my $newt = Text::Tradition->new( 'input' => 'Self', 'string' => $graphml_str );
-is( ref( $newt ), 'Text::Tradition', "Parsed current GraphML version" );
+ok( $newt->$_isa('Text::Tradition'), "Parsed current GraphML version" );
 if( $newt ) {
     is( scalar $newt->collation->readings, 319, "Collation has all readings" );
     is( scalar $newt->collation->paths, 376, "Collation has all paths" );
@@ -138,8 +148,10 @@ if( $newt ) {
     my $rel = $newt->collation->get_relationship( 'w12', 'w13' );
     ok( $rel, "Found set relationship" );
     is( $rel->annotation, 'This is some note', "Relationship has its properties" );
-    is( scalar $newt->stemmata, 1, "Tradition has its stemma" );
-    is( $newt->stemma(0)->witnesses, $t->stemma(0)->witnesses, "Stemma has correct length witness list" );
+    if( $stemma_enabled ) {
+           is( scalar $newt->stemmata, 1, "Tradition has its stemma" );
+       is( $newt->stemma(0)->witnesses, $t->stemma(0)->witnesses, "Stemma has correct length witness list" );
+    }
 }
 
 # Test user save / restore
@@ -151,7 +163,7 @@ my $userstore = Text::Tradition::Directory->new( { dsn => $dsn,
        extra_args => { create => 1 } } );
 my $scope = $userstore->new_scope();
 my $testuser = $userstore->create_user( { url => 'http://example.com' } );
-is( ref( $testuser ), 'Text::Tradition::User', "Created test user via userstore" );
+ok( $testuser->$_isa('Text::Tradition::User'), "Created test user via userstore" );
 $testuser->add_tradition( $newt );
 is( $newt->user->id, $testuser->id, "Assigned tradition to test user" );
 $graphml_str = $newt->collation->as_graphml;
@@ -164,6 +176,14 @@ $usert = Text::Tradition->new( 'input' => 'Self', 'string' => $graphml_str,
        'userstore' => $userstore );
 is( $usert->user->id, $testuser->id, "Parsed tradition with userstore points to correct user" );
 
+# Test warning if we can
+unless( $stemma_enabled ) {
+       my $nst;
+       warnings_exist {
+               $nst = Text::Tradition->new( 'input' => 'Self', 'file' => 't/data/lexformat.xml' );
+       } [qr/DROPPING stemmata/],
+               "Got expected stemma drop warning on parse";
+}
 
 =end testing
 
@@ -190,9 +210,18 @@ sub parse {
                if( $gkey eq 'version' ) {
                        $use_version = $val;
                } elsif( $gkey eq 'stemmata' ) {
+                       # Make sure we can handle stemmata
+                       my $stemma_enabled;
+                       try {
+                               $stemma_enabled = $tradition->enable_stemmata;
+                       } catch {
+                               warn "Analysis module not installed; DROPPING stemmata";
+                       }
                        # Parse the stemmata into objects
-                       foreach my $dotstr ( split( /\n/, $val ) ) {
-                               $tradition->add_stemma( 'dot' => $dotstr );
+                       if( $stemma_enabled ) {
+                               foreach my $dotstr ( split( /\n/, $val ) ) {
+                                       $tradition->add_stemma( 'dot' => $dotstr );
+                               }
                        }
                } elsif( $gkey eq 'user' ) {
                        # Assign the tradition to the user if we can
similarity index 100%
rename from script/analyze.pl
rename to base/script/analyze.pl
similarity index 100%
rename from script/dblookup.pl
rename to base/script/dblookup.pl
similarity index 100%
rename from script/poslink.pl
rename to base/script/poslink.pl
similarity index 100%
rename from t/00dependencies.t
rename to base/t/00dependencies.t
similarity index 100%
rename from t/01app.t
rename to base/t/01app.t
similarity index 100%
rename from t/02pod.t
rename to base/t/02pod.t
similarity index 100%
rename from t/03podcoverage.t
rename to base/t/03podcoverage.t
similarity index 100%
rename from t/data/besoin.xml
rename to base/t/data/besoin.xml
similarity index 100%
rename from t/data/cx16.json
rename to base/t/data/cx16.json
similarity index 100%
rename from t/data/john.xml
rename to base/t/data/john.xml
similarity index 100%
rename from t/data/lf2.xml
rename to base/t/data/lf2.xml
similarity index 100%
rename from t/data/simple.dot
rename to base/t/data/simple.dot
similarity index 100%
rename from t/data/simple.txt
rename to base/t/data/simple.txt
similarity index 100%
rename from t/graph.t
rename to base/t/graph.t
similarity index 100%
rename from t/inline2test.conf
rename to base/t/inline2test.conf
similarity index 85%
rename from t/lexeme_serialize.t
rename to base/t/lexeme_serialize.t
index 7db1bae..401432b 100644 (file)
@@ -1,6 +1,7 @@
 use lib 'lib';
 use strict;
 use warnings;
+use Safe::Isa;
 use Test::More;
 use Text::Tradition;
 
@@ -25,11 +26,11 @@ my $tf2 = Text::Tradition->new(
        string => $graphmlstr,
        language => 'French' );
 
-is( ref $tf2, 'Text::Tradition', "Re-parsed tradition with lemmatization" );
+ok( $tf2->$_isa('Text::Tradition'), "Re-parsed tradition with lemmatization" );
 is( $tf->name, $tf2->name, "Traditions have same name" );
 foreach my $r ( $tf->collation->readings ) {
        my $r2 = $tf2->collation->reading( $r->id );
-       is( ref $r2, 'Text::Tradition::Collation::Reading',
+       ok( $r2->$_isa('Text::Tradition::Collation::Reading'),
                "Reading $r exists in new tradition" );
        if( $r2 ) {
                is( scalar $r->lexemes, scalar $r2->lexemes,
@@ -41,7 +42,7 @@ foreach my $r ( $tf->collation->readings ) {
 my $tf3 = Text::Tradition->new(
        'input' => 'Self',
        'file' => 't/data/lexformat.xml' );
-is( ref $tf3, 'Text::Tradition', 
+ok( $tf3->$_isa('Text::Tradition'), 
        "Successfully parsed tradition with incomplete lexemes" );
 
 done_testing();
similarity index 98%
rename from t/load-save-speed.t
rename to base/t/load-save-speed.t
index ad4bf53..30837da 100644 (file)
@@ -55,7 +55,7 @@ my $tradition = Text::Tradition->new(
 #    'input' => 'Tabular',
 #    'file' => 't/data/simple.txt',
 );
-$tradition->add_stemma(dotfile => "t/data/${test_name}.dot");
+#$tradition->add_stemma(dotfile => "t/data/${test_name}.dot");
 
 #my $fh = File::Temp->new();
 #my $file = $fh->filename;
similarity index 74%
rename from t/text_tradition.t
rename to base/t/text_tradition.t
index 2c7be1b..7e1718a 100644 (file)
@@ -47,25 +47,5 @@ is( scalar $s->witnesses, 3, "object has three witnesses again" );
 
 
 
-# =begin testing
-{
-use Text::Tradition;
-
-my $t = Text::Tradition->new( 
-    'name'  => 'simple test', 
-    'input' => 'Tabular',
-    'file'  => 't/data/simple.txt',
-    );
-
-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" );
-}
-
-
-
 
 1;
similarity index 91%
rename from t/text_tradition_collation.t
rename to base/t/text_tradition_collation.t
index fc7abe1..f1bcba4 100644 (file)
@@ -53,6 +53,7 @@ is( $c->reading('n21p0')->text, 'unto', "Reading n21p0 merged correctly" );
 # =begin testing
 {
 use Text::Tradition;
+use TryCatch;
 
 my $READINGS = 311;
 my $PATHS = 361;
@@ -86,11 +87,20 @@ is( scalar $st->collation->paths, $PATHS, "Reparsed collation has all paths" );
 is( scalar $st->collation->relationships, 3, "Reparsed collation has new relationships" );
 
 # Now add a stemma, write to GraphML, and look at the output.
-my $stemma = $tradition->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
-is( ref( $stemma ), 'Text::Tradition::Stemma', "Parsed dotfile into stemma" );
-is( $tradition->stemmata, 1, "Tradition now has the stemma" );
-$graphml = $c->as_graphml;
-like( $graphml, qr/digraph/, "Digraph declaration exists in GraphML" );
+my $SKIP_STEMMA;
+try {
+       $tradition->enable_stemmata;
+} catch {
+       $SKIP_STEMMA = 1;
+}
+SKIP: {
+       skip "Analysis module not present", 3 if $SKIP_STEMMA;
+       my $stemma = $tradition->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
+       is( ref( $stemma ), 'Text::Tradition::Stemma', "Parsed dotfile into stemma" );
+       is( $tradition->stemmata, 1, "Tradition now has the stemma" );
+       $graphml = $c->as_graphml;
+       like( $graphml, qr/digraph/, "Digraph declaration exists in GraphML" );
+}
 
 # Now add a user, write to GraphML, and look at the output.
 unlike( $graphml, qr/testuser/, "Test user name does not exist in GraphML yet" );
similarity index 55%
rename from t/text_tradition_directory.t
rename to base/t/text_tradition_directory.t
index 8950148..1eaa598 100644 (file)
@@ -10,6 +10,7 @@ $| = 1;
 {
 use TryCatch;
 use File::Temp;
+use Safe::Isa;
 use Text::Tradition;
 use_ok 'Text::Tradition::Directory';
 
@@ -23,26 +24,31 @@ my $t = Text::Tradition->new(
        'input' => 'Tabular',
        'file'  => 't/data/simple.txt',
        );
+my $stemma_enabled;
+eval { $stemma_enabled = $t->enable_stemmata; };
 
 {
        my $d = Text::Tradition::Directory->new( 'dsn' => $dsn,
                'extra_args' => { 'create' => 1 } );
-       is( ref $d, 'Text::Tradition::Directory', "Got directory object" );
+       ok( $d->$_isa('Text::Tradition::Directory'), "Got directory object" );
        
        my $scope = $d->new_scope;
        $uuid = $d->save( $t );
        ok( $uuid, "Saved test tradition" );
        
-       my $s = $t->add_stemma( dotfile => 't/data/simple.dot' );
-       ok( $d->save( $t ), "Updated tradition with stemma" );
-       is( $d->tradition( $uuid ), $t, "Correct tradition returned for id" );
-       is( $d->tradition( $uuid )->stemma(0), $s, "...and it has the correct stemma" );
-       try {
-               $d->save( $s );
-       } catch( Text::Tradition::Error $e ) {
-               is( $e->ident, 'database error', "Got exception trying to save stemma directly" );
-               like( $e->message, qr/Cannot directly save non-Tradition object/, 
-                       "Exception has correct message" );
+       SKIP: {
+               skip "Analysis package not installed", 5 unless $stemma_enabled;
+               my $s = $t->add_stemma( dotfile => 't/data/simple.dot' );
+               ok( $d->save( $t ), "Updated tradition with stemma" );
+               is( $d->tradition( $uuid ), $t, "Correct tradition returned for id" );
+               is( $d->tradition( $uuid )->stemma(0), $s, "...and it has the correct stemma" );
+               try {
+                       $d->save( $s );
+               } catch( Text::Tradition::Error $e ) {
+                       is( $e->ident, 'database error', "Got exception trying to save stemma directly" );
+                       like( $e->message, qr/Cannot directly save non-Tradition object/, 
+                               "Exception has correct message" );
+               }
        }
 }
 my $nt = Text::Tradition->new(
@@ -50,7 +56,7 @@ my $nt = Text::Tradition->new(
        'input' => 'CollateX',
        'file' => 't/data/Collatex-16.xml',
        );
-is( ref( $nt ), 'Text::Tradition', "Made new tradition" );
+ok( $nt->$_isa('Text::Tradition'), "Made new tradition" );
 
 {
        my $f = Text::Tradition::Directory->new( 'dsn' => $dsn );
@@ -64,24 +70,28 @@ is( ref( $nt ), 'Text::Tradition', "Made new tradition" );
        my( $tlobj ) = grep { $_->{'id'} eq $uuid } @tlist;
        is( $tlobj->{'name'}, $tf->name, "Directory index has correct tradition name" );
        is( $tf->name, $t->name, "Retrieved the tradition from a new directory" );
-       my $sid = $f->object_to_id( $tf->stemma(0) );
-       try {
-               $f->tradition( $sid );
-       } catch( Text::Tradition::Error $e ) {
-               is( $e->ident, 'database error', "Got exception trying to fetch stemma directly" );
-               like( $e->message, qr/not a Text::Tradition/, "Exception has correct message" );
-       }
-       try {
-               $f->delete( $sid );
-       } catch( Text::Tradition::Error $e ) {
-               is( $e->ident, 'database error', "Got exception trying to delete stemma directly" );
-               like( $e->message, qr/Cannot directly delete non-Tradition object/, 
-                       "Exception has correct message" );
+       my $sid;
+       SKIP: {
+               skip "Analysis package not installed", 4 unless $stemma_enabled;
+               $sid = $f->object_to_id( $tf->stemma(0) );
+               try {
+                       $f->tradition( $sid );
+               } catch( Text::Tradition::Error $e ) {
+                       is( $e->ident, 'database error', "Got exception trying to fetch stemma directly" );
+                       like( $e->message, qr/not a Text::Tradition/, "Exception has correct message" );
+               }
+               try {
+                       $f->delete( $sid );
+               } catch( Text::Tradition::Error $e ) {
+                       is( $e->ident, 'database error', "Got exception trying to delete stemma directly" );
+                       like( $e->message, qr/Cannot directly delete non-Tradition object/, 
+                               "Exception has correct message" );
+               }
        }
        
        $f->delete( $uuid );
        ok( !$f->exists( $uuid ), "Object is deleted from DB" );
-       ok( !$f->exists( $sid ), "Object stemma also deleted from DB" );
+       ok( !$f->exists( $sid ), "Object stemma also deleted from DB" ) if $stemma_enabled;
        is( scalar $f->traditionlist, 1, "Object is deleted from index" );
 }
 
similarity index 74%
rename from t/text_tradition_parser_self.t
rename to base/t/text_tradition_parser_self.t
index 5583932..35aa695 100644 (file)
@@ -9,8 +9,10 @@ $| = 1;
 # =begin testing
 {
 use File::Temp;
+use Safe::Isa;
 use Test::Warn;
 use Text::Tradition;
+use TryCatch;
 binmode STDOUT, ":utf8";
 binmode STDERR, ":utf8";
 eval { no warnings; binmode $DB::OUT, ":utf8"; };
@@ -22,7 +24,7 @@ my $t = Text::Tradition->new(
     'file'  => $tradition,
     );
 
-is( ref( $t ), 'Text::Tradition', "Parsed GraphML version 2" );
+ok( $t->$_isa('Text::Tradition'), "Parsed GraphML version 2" );
 if( $t ) {
     is( scalar $t->collation->readings, 319, "Collation has all readings" );
     is( scalar $t->collation->paths, 376, "Collation has all paths" );
@@ -32,7 +34,15 @@ if( $t ) {
 # TODO add a relationship, add a stemma, write graphml, reparse it, check that 
 # the new data is there
 $t->language('Greek');
-$t->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
+my $stemma_enabled;
+try {
+       $stemma_enabled = $t->enable_stemmata;
+} catch {
+       ok( 1, "Skipping stemma tests without Analysis module" );
+}
+if( $stemma_enabled ) {
+       $t->add_stemma( 'dotfile' => 't/data/florilegium.dot' );
+}
 $t->collation->add_relationship( 'w12', 'w13', 
        { 'type' => 'grammatical', 'scope' => 'global', 
          'annotation' => 'This is some note' } );
@@ -40,7 +50,7 @@ ok( $t->collation->get_relationship( 'w12', 'w13' ), "Relationship set" );
 my $graphml_str = $t->collation->as_graphml;
 
 my $newt = Text::Tradition->new( 'input' => 'Self', 'string' => $graphml_str );
-is( ref( $newt ), 'Text::Tradition', "Parsed current GraphML version" );
+ok( $newt->$_isa('Text::Tradition'), "Parsed current GraphML version" );
 if( $newt ) {
     is( scalar $newt->collation->readings, 319, "Collation has all readings" );
     is( scalar $newt->collation->paths, 376, "Collation has all paths" );
@@ -50,8 +60,10 @@ if( $newt ) {
     my $rel = $newt->collation->get_relationship( 'w12', 'w13' );
     ok( $rel, "Found set relationship" );
     is( $rel->annotation, 'This is some note', "Relationship has its properties" );
-    is( scalar $newt->stemmata, 1, "Tradition has its stemma" );
-    is( $newt->stemma(0)->witnesses, $t->stemma(0)->witnesses, "Stemma has correct length witness list" );
+    if( $stemma_enabled ) {
+           is( scalar $newt->stemmata, 1, "Tradition has its stemma" );
+       is( $newt->stemma(0)->witnesses, $t->stemma(0)->witnesses, "Stemma has correct length witness list" );
+    }
 }
 
 # Test user save / restore
@@ -63,7 +75,7 @@ my $userstore = Text::Tradition::Directory->new( { dsn => $dsn,
        extra_args => { create => 1 } } );
 my $scope = $userstore->new_scope();
 my $testuser = $userstore->create_user( { url => 'http://example.com' } );
-is( ref( $testuser ), 'Text::Tradition::User', "Created test user via userstore" );
+ok( $testuser->$_isa('Text::Tradition::User'), "Created test user via userstore" );
 $testuser->add_tradition( $newt );
 is( $newt->user->id, $testuser->id, "Assigned tradition to test user" );
 $graphml_str = $newt->collation->as_graphml;
@@ -75,6 +87,15 @@ warning_is {
 $usert = Text::Tradition->new( 'input' => 'Self', 'string' => $graphml_str,
        'userstore' => $userstore );
 is( $usert->user->id, $testuser->id, "Parsed tradition with userstore points to correct user" );
+
+# Test warning if we can
+unless( $stemma_enabled ) {
+       my $nst;
+       warnings_exist {
+               $nst = Text::Tradition->new( 'input' => 'Self', 'file' => 't/data/lexformat.xml' );
+       } [qr/DROPPING stemmata/],
+               "Got expected stemma drop warning on parse";
+}
 }