Text-Tradition-Directory

 view release on metacpan or  search on metacpan

lib/Text/Tradition/Directory.pm  view on Meta::CPAN

	my @w1 = sort { $a->sigil cmp $b->sigil } $ntobj->witnesses;
	my @w2 = sort{ $a->sigil cmp $b->sigil } $nt->witnesses;
	is_deeply( \@w1, \@w2, "Looked up remaining tradition by name" );
}

=end testing

=cut
use Text::Tradition::TypeMap::Entry;

has +typemap => (
  is      => 'rw',
  isa     => 'KiokuDB::TypeMap',
  default => sub {
    KiokuDB::TypeMap->new(
      isa_entries => {
	# now that we fall back to YAML deflation, all attributes of
	# Text::Tradition will be serialized to YAML as individual objects
	# Except if we declare a specific entry type here
        "Text::Tradition" =>
          KiokuDB::TypeMap::Entry::MOP->new(),
	# We need users to be naive entries so that they hold
	# references to the original tradition objects, not clones
        "Text::Tradition::User" =>
          KiokuDB::TypeMap::Entry::MOP->new(),
        "Text::Tradition::Collation" =>
          KiokuDB::TypeMap::Entry::MOP->new(),
        "Text::Tradition::Witness" =>
          KiokuDB::TypeMap::Entry::MOP->new(),
        "Graph" => Text::Tradition::TypeMap::Entry->new(),
        "Set::Scalar" => Text::Tradition::TypeMap::Entry->new(),
      }
    );
  },
);

has '_mysql_utf8_hack' => (
	is => 'ro',
	isa => 'Bool',
	default => undef,
);

# Push some columns into the extra_args
around BUILDARGS => sub {
	my $orig = shift;
	my $class = shift;
	my $args;
	if( @_ == 1 ) {
		$args = $_[0];
	} else {
		$args = { @_ };
	}
	my @column_args;
	if( $args->{'dsn'} =~ /^dbi:(\w+):/ ) { # We're using Backend::DBI
		my $dbtype = $1;
		@column_args = ( 'columns',
			[ 'name' => { 'data_type' => 'varchar', 'is_nullable' => 1 },
			  'public' => { 'data_type' => 'bool', 'is_nullable' => 1 } ] );
		if( $dbtype eq 'mysql' && 
			exists $args->{extra_args}->{dbi_attrs} &&
			$args->{extra_args}->{dbi_attrs}->{mysql_enable_utf8} ) {
			# There is a bad interaction with MySQL in utf-8 mode.
			# Work around it here.
			# TODO fix the underlying storage problem
			$args->{extra_args}->{dbi_attrs}->{mysql_enable_utf8} = undef;
			$args->{_mysql_utf8_hack} = 1;
		}
	}
	my $ea = $args->{'extra_args'};
	if( ref( $ea ) eq 'ARRAY' ) {
		push( @$ea, @column_args );
	} elsif( ref( $ea ) eq 'HASH' ) {
		$ea = { %$ea, @column_args };
	} else {
		$ea = { @column_args };
	}
	$args->{'extra_args'} = $ea;

	return $class->$orig( $args );
};

override _build_directory => sub {
  my($self) = @_;
  Text::Tradition::Store->connect(@{ $self->_connect_args },
    resolver_constructor => sub {
      my($class) = @_;
      $class->new({ typemap => $self->directory->merged_typemap,
                    fallback_entry => Text::Tradition::TypeMap::Entry->new() });
  });
};

## These checks don't cover store($id, $obj)
# before [ qw/ store update insert delete / ] => sub {
before [ qw/ delete / ] => sub {
	my $self = shift;
	my @nontrad;
	foreach my $obj ( @_ ) {
		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 $obj->{$k}->$_isa('Text::Tradition');
			}
			push( @nontrad, $obj );
		}
	}
	if( @nontrad ) {
		throw( "Cannot directly save non-Tradition object of type "
			. ref( $nontrad[0] ) );
	}
};

# TODO Garbage collection doesn't work. Suck it up and live with the 
# inflated DB.
after delete => sub {
	my $self = shift;
	my $gc = KiokuDB::GC::Naive->new( backend => $self->directory->backend );
	$self->directory->backend->delete( $gc->garbage->members );
};

sub save {
	my $self = shift;
	return $self->store( @_ );
}



( run in 2.446 seconds using v1.01-cache-2.11-cpan-2398b32b56e )