Elive
view release on metacpan or search on metacpan
lib/Elive/DAO.pm view on Meta::CPAN
package Elive::DAO;
use warnings; use strict;
use Mouse;
use Mouse::Util::TypeConstraints;
our $VERSION = '1.37';
use parent 'Elive::DAO::_Base';
use YAML::Syck;
use Scalar::Util qw{weaken};
use Carp;
use Try::Tiny;
use URI;
use Elive::Util qw{1.37};
__PACKAGE__->mk_classdata('_entities' => {});
__PACKAGE__->mk_classdata('_aliases');
__PACKAGE__->mk_classdata('_derivable' => {});
__PACKAGE__->mk_classdata('_entity_name');
__PACKAGE__->mk_classdata('_primary_key' => []);
__PACKAGE__->mk_classdata('_params' => {});
__PACKAGE__->mk_classdata('collection_name');
__PACKAGE__->mk_classdata('_isa');
foreach my $accessor (qw{_db_data _deleted _is_copy}) {
__PACKAGE__->has_metadata($accessor);
}
=head1 NAME
Elive::DAO - Abstract class for Elive Data Access Objects
=head1 DESCRIPTION
This is an abstract class for retrieving and managing objects mapped to a
datastore.
=cut
our %Stored_Objects;
sub BUILDARGS {
my ($class, $raw, @args) = @_;
warn "$class - ignoring arguments to new: @args\n"
if @args;
if (Elive::Util::_reftype($raw) eq 'HASH') {
my $types = $class->property_types;
my %cooked;
my $aliases = $class->_get_aliases;
foreach (keys %$raw) {
#
# apply any aliases
#
my $prop = (exists $aliases->{$_}
? ($aliases->{$_}{to} or die "$class has malformed alias: $_")
: $_);
my $value = $raw->{$_};
if (my $type = $types->{$prop}) {
if (ref($value)) {
#
lib/Elive/DAO.pm view on Meta::CPAN
my $type = Elive::Util::_reftype( $struct );
if ($type) {
if (Scalar::Util::blessed $struct
&& $struct->can('_is_copy')) {
$opt{copy} ||= $struct->_is_copy;
$struct->_is_copy(1)
if $opt{copy};
}
# recurse
if ($type eq 'ARRAY') {
foreach (0 .. scalar(@$struct)) {
$struct->[$_] = __set_db_data($struct->[$_], $data_copy->[$_], %opt)
if ref $struct->[$_];
}
}
elsif ($type eq 'HASH') {
foreach (sort keys %$struct) {
$struct->{$_} = __set_db_data($struct->{$_}, $data_copy->{$_}, %opt)
if ref $struct->{$_};
}
}
else {
warn "don't know how to set db data for sub-type $type";
}
if (Scalar::Util::blessed $struct) {
if ($connection && $struct->can('connection')) {
if (!$opt{copy}
&& $struct->can('url')
&& (my $obj_url = $struct->url($connection))
) {
my $cache_access;
if (my $cached = $Stored_Objects{ $obj_url }) {
$cache_access = 'reuse';
#
# Overwrite the cached object, then reuse it.
#
die "attempted overwrite of object with unsaved changes ($obj_url)"
if !$opt{overwrite} && $cached->is_changed;
die "cache type conflict. $obj_url contains an ".ref($cached)." object, but requested ".ref($struct)
unless $cached->isa(ref($struct));
%{$cached} = %{$struct};
$struct = $cached;
}
else {
$cache_access = 'init';
}
# rewrite, for benefit of 5.13.3
weaken ($Stored_Objects{$obj_url} = $struct);
if ($struct->debug >= 5) {
warn YAML::Syck::Dump({opt => \%opt, struct => $struct, class => ref($struct), url => $obj_url, cache => $cache_access, ref1 => "$struct", ref2 => "$Stored_Objects{$obj_url}"});
}
}
$struct->connection( $connection );
}
if ($struct->can('_db_data')) {
#
# save before image from database
#
$data_copy->_db_data(undef)
if Scalar::Util::blessed($data_copy)
&& $data_copy->can('_db_data');
$struct->_db_data($data_copy);
}
}
}
return $struct;
}
#
# _freeze - construct name/value pairs for database inserts or updates
#
sub _freeze {
my $class = shift;
my $db_data = shift;
my %opt = @_;
$db_data ||= $class if ref($class);
$db_data ||= {};
$db_data = Elive::Util::_clone( $db_data );
my $property_types = $class->property_types || {};
my %param_types = $class->params;
$class->_canonicalize_properties( $db_data );
foreach (keys %$db_data) {
my $property = $property_types->{$_} || $param_types{$_};
unless ($property) {
my @properties = $class->properties;
my @param_names = sort keys %param_types;
Carp::croak "$class: unknown property/parameter: $_: expected: ",join(',', @properties, @param_names);
}
my $type_info = Elive::Util::inspect_type($property);
my $type = $type_info->elemental_type;
my $is_array = $type_info->is_array;
for ($db_data->{$_}) {
$_ = Elive::Util::_freeze($_, $is_array ? $property : $type);
( run in 0.444 second using v1.01-cache-2.11-cpan-0d23b851a93 )