Use dzil Authority plugin - remove $AUTHORITY from code
[gitmo/Moose.git] / lib / Moose / Meta / Role / Attribute.pm
1 package Moose::Meta::Role::Attribute;
2
3 use strict;
4 use warnings;
5
6 use Carp 'confess';
7 use List::MoreUtils 'all';
8 use Scalar::Util 'blessed', 'weaken';
9
10 use base 'Moose::Meta::Mixin::AttributeCore', 'Class::MOP::Object';
11
12 __PACKAGE__->meta->add_attribute(
13     'metaclass' => (
14         reader => 'metaclass',
15     )
16 );
17
18 __PACKAGE__->meta->add_attribute(
19     'associated_role' => (
20         reader => 'associated_role',
21     )
22 );
23
24 __PACKAGE__->meta->add_attribute(
25     'is' => (
26         reader => 'is',
27     )
28 );
29
30 __PACKAGE__->meta->add_attribute(
31     'original_options' => (
32         reader => 'original_options',
33     )
34 );
35
36 sub new {
37     my ( $class, $name, %options ) = @_;
38
39     (defined $name)
40         || confess "You must provide a name for the attribute";
41
42     return bless {
43         name             => $name,
44         original_options => \%options,
45         %options,
46     }, $class;
47 }
48
49 sub attach_to_role {
50     my ( $self, $role ) = @_;
51
52     ( blessed($role) && $role->isa('Moose::Meta::Role') )
53         || confess
54         "You must pass a Moose::Meta::Role instance (or a subclass)";
55
56     weaken( $self->{'associated_role'} = $role );
57 }
58
59 sub attribute_for_class {
60     my $self      = shift;
61     my $metaclass = shift;
62
63     return $metaclass->interpolate_class_and_new(
64         $self->name => %{ $self->original_options } );
65 }
66
67 sub clone {
68     my $self = shift;
69
70     return ( ref $self )->new( $self->name, %{ $self->original_options } );
71 }
72
73 sub is_same_as {
74     my $self = shift;
75     my $attr = shift;
76
77     my $self_options = $self->original_options;
78     my $other_options = $attr->original_options;
79
80     return 0
81         unless ( join q{|}, sort keys %{$self_options} ) eq ( join q{|}, sort keys %{$other_options} );
82
83     for my $key ( keys %{$self_options} ) {
84         return 0 if defined $self_options->{$key} && ! defined $other_options->{$key};
85         return 0 if ! defined $self_options->{$key} && defined $other_options->{$key};
86
87         next if all { ! defined } $self_options->{$key}, $other_options->{$key};
88
89         return 0 unless $self_options->{$key} eq $other_options->{$key};
90     }
91
92     return 1;
93 }
94
95 1;
96
97 =pod
98
99 =head1 DESCRIPTION
100
101 This class implements the API for attributes in roles. Attributes in roles are
102 more like attribute prototypes than full blown attributes. While they are
103 introspectable, they have very little behavior.
104
105 =head1 METHODS
106
107 This class provides the following methods:
108
109 =over 4
110
111 =item B<< Moose::Meta::Role::Attribute->new(...) >>
112
113 This method accepts all the options that would be passed to the constructor
114 for L<Moose::Meta::Attribute>.
115
116 =item B<< $attr->metaclass >>
117
118 =item B<< $attr->is >>
119
120 Returns the option as passed to the constructor.
121
122 =item B<< $attr->associated_role >>
123
124 Returns the L<Moose::Meta::Role> to which this attribute belongs, if any.
125
126 =item B<< $attr->original_options >>
127
128 Returns a hash reference of options passed to the constructor. This is used
129 when creating a L<Moose::Meta::Attribute> object from this object.
130
131 =item B<< $attr->attach_to_role($role) >>
132
133 Attaches the attribute to the given L<Moose::Meta::Role>.
134
135 =item B<< $attr->attribute_for_class($metaclass) >>
136
137 Given an attribute metaclass name, this method calls C<<
138 $metaclass->interpolate_class_and_new >> to construct an attribute object
139 which can be added to a L<Moose::Meta::Class>.
140
141 =item B<< $attr->clone >>
142
143 Creates a new object identical to the object on which the method is called.
144
145 =item B<< $attr->is_same_as($other_attr) >>
146
147 Compares two role attributes and returns true if they are identical.
148
149 =back
150
151 In addition, this class implements all informational predicates implements by
152 L<Moose::Meta::Attribute> (and L<Class::MOP::Attribute>).
153
154 =head1 BUGS
155
156 See L<Moose/BUGS> for details on reporting bugs.
157
158 =cut