Data-AnyXfer

 view release on metacpan or  search on metacpan

lib/Data/AnyXfer/Elastic/Import/Storage/Directory.pm  view on Meta::CPAN

package Data::AnyXfer::Elastic::Import::Storage::Directory;

use Moo;
use MooX::Types::MooseLike::Base qw(:all);

use Carp;
use Path::Class           ();
use File::Copy::Recursive ();
use Data::AnyXfer         ();

=head1 NAME

Data::AnyXfer::Elastic::Import::Storage::Directory -
 Filesystem directory-based import storage

=head1 SYNOPSIS

    my $storage =
        Data::AnyXfer::Elastic::Import::Storage::Directory->new;

    $storage->set(
        company => 'Limited',
        address =>
            'Building One, Chiswick Park, 566 Chiswick High Road, London W4 5BE',
        regno => 1680058,
    );

    $storage->save;

=head1 DESCRIPTION

This module implements L<Data::AnyXfer::Elastic::Import::Storage>,
based on filesystem directories.

It uses temporary working directories, with persistence to an optional final
target directory on L<Data::AnyXfer::Elastic::Import::Storage/save>.

It represents items as single files, and can only store printable characters
(i.e. any complex content should be serialised to a representable format
before being passed to this module to store).

=cut

=head1 ATTRIBUTES

=over

=item B<dir>

Optional. The final target directory that data should be persisted to.

=item B<working_dir>

Optional. The temporary directory data should be written to as operations are performed
on this instance.

=item B<item_file_suffix>

Optional. A string that will be appended to the end of every item name transparently
when written to storage (will not be visible through the storage interface).

You can also use this for file extensions.

=item B<item_file_prefix>

Optional. A string that will be prepended to the start of every item name transparently
when written to storage (will not be visible through the storage interface).

=back

=head1 STORAGE INTERFACE

B<Please see L<Data::AnyXfer::Elastic::Import::Storage> for the
interface definition and information>.

=cut


# ATTRIBUTES


has dir => (
    is      => 'ro',
    isa     => InstanceOf['Path::Class::Dir'],
    builder => '_setup_default_dir',
);

has read_only => (
    is      => 'ro',
    isa     => Bool,
    default => 0,
);

has working_dir => (
    is      => 'ro',
    isa     => InstanceOf['Path::Class::Dir'],
    lazy    => 1,
    builder => '_setup_and_init_working_dir',
);

has item_file_suffix => (
    is      => 'ro',
    isa     => Str,
    default => '',
);

has item_file_prefix => (
    is      => 'ro',
    isa     => Str,
    default => '',
);

has destination_info => (
    is  => 'ro',
    isa => Str,
);

has _item_list => (
    is      => 'bare',
    isa     => ArrayRef,
    default => sub { [] },
);

has _item_map => (
    is      => 'bare',
    isa     => HashRef,

lib/Data/AnyXfer/Elastic/Import/Storage/Directory.pm  view on Meta::CPAN

    # otherwise fail
    # (in list context, we also return the file also)
    return wantarray() ? ( 0, $file ) : 0;
}


sub _export_internal_item_map {

    my $self = $_[0];
    return { %{ $self->{_item_map} } };
}


sub _setup_and_init_working_dir {

    my $self = $_[0];

    # create a temp dir using default dir setup
    my $working_dir = $self->_setup_default_dir;

    # if we have a source / working_dir dir, copy it
    if ( my $source_dir = $self->dir ) {

        unless ( File::Copy::Recursive::dircopy( $source_dir, $working_dir ) )
        {
            croak 'Failed to temp copy of source datafile directory: '
                . $source_dir;
        }
    }
    return $working_dir;
}

sub _setup_default_dir {

    my $self = $_[0];

    # create a temporary directory
    my $dir = Data::AnyXfer->tmp_dir(
        { name => 'es_import_datefile', cleanup => 1 } );

    # resolve the path and make sure it's empty
    $dir = Path::Class::dir($dir)->resolve;
    $dir->rmtree;

    # re-create it and return
    $dir->mkpath;

    return $dir;
}


=head2 convert_item_name

    my $item =
        $self->convert_item_name('some_random_string_with_unknown_chars');

Converts an arbritrary string to a format safe to be used by this storage
backend as an item name.

This is not necessary on storage interface methods as this is handled
transparently for you.

=head3 CAVEATS

This convertion is most likely one-way (lossy). Because of the normalisation,
different strings can point to the same item,
e.g. 'some_string' and 'some-string' are considered the same item.

=cut

sub convert_item_name {

    my $suffix = $_[0]->item_file_suffix || '';
    my $prefix = $_[0]->item_file_prefix || '';

    my $name = sprintf "%s%s%s", $prefix, $_[1], $suffix;
    $name =~ s/([ ]+|[-\.]{2,})/-/g;
    $name =~ s/[^A-Za-z0-9-\.]/-/g;
    $name =~ s/-+/-/g;
    return $name;
}




1;

=head1 COPYRIGHT

This software is copyright (c) 2019, Anthony Lucas.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

=cut



( run in 1.556 second using v1.01-cache-2.11-cpan-39bf76dae61 )