Data-Downloader
view release on metacpan or search on metacpan
lib/Data/Downloader/Config.pm view on Meta::CPAN
use YAML::XS qw/Dump Load LoadFile/;
use Scalar::Util qw/looks_like_number/;
use Data::Dumper;
use strict;
use warnings;
=head1 METHODS
=over
=item init
Inserts information about repository and feeds
using a config file.
Parameters :
filename: the name of a config file
yaml: yaml content of the file (can be sent instead of file)
update_ok: allow updates, not just initialization
=cut
sub init {
my $self = shift;
my $args = validate(@_, { file => 0, filename => 0, yaml => 0, update_ok => 0 } );
my $file = $args->{file} || $args->{filename};
DEBUG "initializing database from ".($file ? "file $file" : "yaml");
my @repositories = $args->{yaml} ? Load($args->{yaml}) : LoadFile($file);
DEBUG "Configuration has ".@repositories." repository(ies)";
for my $repository_spec (@repositories) {
TRACE "repository : ".$repository_spec->{name};
my $repository = Data::Downloader::Repository->new(name => $repository_spec->{name});
if ($repository->load(speculative => 1)) {
if ($args->{update_ok}) {
_recursive_object_update($repository,$repository_spec);
} else {
LOGDIE "Existing repository ".$repository->name." found. ".
"To re-initialize, remove ".$repository->db->database.
". To update, set update_ok to be true.";
}
} else {
# XXX not bulletproof -- the new one may refer to existing feeds, etc.
INFO "creating new repository $repository_spec->{name}";
$repository = Data::Downloader::Repository->new(%$repository_spec);
$repository->save or LOGDIE "Error saving repository $repository_spec->{name}: ".$repository->error;
}
}
Data::Downloader::MetadataPivot->rebuild_pivot_view;
}
=item update
Update the config
=cut
sub update {
my $self = shift;
my %args = @_;
$args{update_ok} = 1;
$self->init(%args);
}
sub _p { defined($_[0]) ? "[$_[0]]" : '[undef]' };
sub _are_same {
my ($x,$y) = @_;
return 0 if defined($x) && !defined($y);
return 0 if !defined($x) && defined($y);
return 1 if !defined($x) && !defined($y);
# ok, both are defined
if (looks_like_number($x) && looks_like_number($y)) {
return ($x==$y);
}
return ($x eq $y);
}
our %classDone; # prevent loops for one-one relationships
our %allowConfig = map { ($_ => 1) } qw/repository
disk feed feed_parameter metadata_source file_source linktree metadata_transformation/;
sub _recursive_object_update {
my $object = shift;
my $spec = shift;
# $object should have already been loaded
# Update all attributes which are not objects.
# Then find child objects and recursively update existing ones.
TRACE "examining table ".$object->meta->table.($object->can('id') ? $object->id : $object);
# one base case
if (!defined($spec)) {
INFO "Deleting ".$object->meta->table." ".($object->can('id') ? $object->id : $object);
$object->delete or LOGDIE "error during delete : ".$object->error;
return;
}
# other base cases
for my $column_name (keys %$spec) {
TRACE "column $column_name";
my ($column) = grep { $_->accessor_method_name eq $column_name } $object->meta->columns;
next unless $column; # not a column, must be a relationship
next if $column->is_primary_key_member;
next if $column_name =~ /^(root|name|order_key)$/; # primary keys, don't allow changing
die "'$column' not defined, name is '$column_name' " unless exists($spec->{$column_name});
TRACE "comparing ".($object->meta->table).".$column : "._p($object->$column)." vs "._p($spec->{$column_name});
next if _are_same($object->$column,$spec->{$column_name});
INFO "Changing ".$object->meta->table." $column_name from "._p($object->$column)." to "._p($spec->{$column_name});
$object->$column($spec->{$column});
$object->save or LOGDIE "error saving changes to ".$object->meta->table." : ".$object->error;
}
# recursive case
for my $relationship ($object->meta->relationships) {
my $method_name = $relationship->method_name('get_set_on_save');
next if $classDone{$relationship->class}++;
next unless $allowConfig{$relationship->class->meta->table};
next unless $relationship->type eq 'one to many' || $relationship->type eq 'one to one';
my $sub_object_spec = $spec->{$method_name};
$sub_object_spec = [ $sub_object_spec ] if $sub_object_spec && ref($sub_object_spec) ne 'ARRAY';
for my $sub_object ($object->$method_name) {
( run in 1.917 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )