From b274df4c9da24b117a22e287acd03b3fa87233a8 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 21 Feb 2011 16:04:51 -0600 Subject: rename MooseX::Bread::Board -> Bread::Board::Declare --- lib/Bread/Board/Declare/Meta/Role/Attribute.pm | 185 +++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 lib/Bread/Board/Declare/Meta/Role/Attribute.pm (limited to 'lib/Bread/Board/Declare/Meta/Role/Attribute.pm') diff --git a/lib/Bread/Board/Declare/Meta/Role/Attribute.pm b/lib/Bread/Board/Declare/Meta/Role/Attribute.pm new file mode 100644 index 0000000..5cd4434 --- /dev/null +++ b/lib/Bread/Board/Declare/Meta/Role/Attribute.pm @@ -0,0 +1,185 @@ +package Bread::Board::Declare::Meta::Role::Attribute; +use Moose::Role; +Moose::Util::meta_attribute_alias('Service'); + +use Bread::Board::Types; +use List::MoreUtils qw(any); + +use Bread::Board::Declare::BlockInjection; +use Bread::Board::Declare::ConstructorInjection; +use Bread::Board::Declare::Literal; + +has service => ( + is => 'ro', + isa => 'Bool', + default => 1, +); + +has block => ( + is => 'ro', + isa => 'CodeRef', + predicate => 'has_block', +); + +# has_value is already a method +has literal_value => ( + is => 'ro', + isa => 'Str|CodeRef', + init_arg => 'value', + predicate => 'has_literal_value', +); + +has lifecycle => ( + is => 'ro', + isa => 'Str', + predicate => 'has_lifecycle', +); + +has dependencies => ( + is => 'ro', + isa => 'Bread::Board::Service::Dependencies', + coerce => 1, + predicate => 'has_dependencies', +); + +has constructor_name => ( + is => 'ro', + isa => 'Str', + predicate => 'has_constructor_name', +); + +has associated_service => ( + is => 'rw', + isa => 'Bread::Board::Service', + predicate => 'has_associated_service', +); + +after attach_to_class => sub { + my $self = shift; + + return unless $self->service; + + my %params = ( + associated_attribute => $self, + name => $self->name, + ($self->has_lifecycle + ? (lifecycle => $self->lifecycle) + : ()), + ($self->has_dependencies + ? (dependencies => $self->dependencies) + : ()), + ($self->has_constructor_name + ? (constructor_name => $self->constructor_name) + : ()), + ); + + my $service; + if ($self->has_block) { + $service = Bread::Board::Declare::BlockInjection->new( + %params, + block => $self->block, + ); + } + elsif ($self->has_literal_value) { + $service = Bread::Board::Declare::Literal->new( + %params, + value => $self->literal_value, + ); + } + elsif ($self->has_type_constraint) { + my $tc = $self->type_constraint; + if ($tc->isa('Moose::Meta::TypeConstraint::Class')) { + $service = Bread::Board::Declare::ConstructorInjection->new( + %params, + class => $tc->class, + ); + } + } + + $self->associated_service($service) if $service; +}; + +after _process_options => sub { + my $class = shift; + my ($name, $opts) = @_; + + return unless exists $opts->{default} + || exists $opts->{builder}; + return unless exists $opts->{class} + || exists $opts->{block} + || exists $opts->{value}; + + # XXX: uggggh + return if any { $_ eq 'Moose::Meta::Attribute::Native::Trait::String' + || $_ eq 'Moose::Meta::Attribute::Native::Trait::Counter' } + @{ $opts->{traits} }; + + my $exists = exists($opts->{default}) ? 'default' : 'builder'; + die "$exists is not valid when Bread::Board service options are set"; +}; + +around get_value => sub { + my $orig = shift; + my $self = shift; + my ($instance) = @_; + + return $self->$orig($instance) + if $self->has_value($instance); + + my $val = $instance->get_service($self->name)->get; + + $self->verify_against_type_constraint($val, instance => $instance) + if $self->has_type_constraint; + + if ($self->should_auto_deref) { + if (ref($val) eq 'ARRAY') { + return wantarray ? @$val : $val; + } + elsif (ref($val) eq 'HASH') { + return wantarray ? %$val : $val; + } + else { + die 'XXX'; + } + } + else { + return $val; + } +}; + +if (Moose->VERSION > 1.9900) { + around _inline_instance_get => sub { + my $orig = shift; + my $self = shift; + my ($instance) = @_; + return 'do {' . "\n" + . 'my $val;' . "\n" + . 'if (' . $self->_inline_instance_has($instance) . ') {' . "\n" + . '$val = ' . $self->$orig($instance) . ';' . "\n" + . '}' . "\n" + . 'else {' . "\n" + . '$val = ' . $instance . '->get_service(\'' . $self->name . '\')->get;' . "\n" + . $self->_inline_check_constraint( + '$val', '$type_constraint', '$type_constraint_obj' + ) + . '}' . "\n" + . '$val' . "\n" + . '}'; + }; +} +else { + around accessor_metaclass => sub { + my $orig = shift; + my $self = shift; + + return Moose::Meta::Class->create_anon_class( + superclasses => [ $self->$orig(@_) ], + roles => [ 'Bread::Board::Declare::Meta::Role::Accessor' ], + cache => 1 + )->name; + }; +} + +no Moose::Role; + +1; -- cgit v1.2.3-54-g00ecf