bump up Moose dep (RT#53016), release
[gitmo/MooseX-Types.git] / lib / MooseX / Types / TypeDecorator.pm
CommitLineData
4c2125a4 1package MooseX::Types::TypeDecorator;
cec62c79 2our $VERSION = "0.21";
4c2125a4 3
a706b0f2 4use strict;
5use warnings;
4c2125a4 6
c1260541 7
bb5b7b28 8use Carp::Clan qw( ^MooseX::Types );
475bbd1d 9use Moose::Util::TypeConstraints ();
bb5b7b28 10use Moose::Meta::TypeConstraint::Union;
371efa05 11use Scalar::Util qw(blessed);
bb5b7b28 12
4c2125a4 13use overload(
14 '""' => sub {
c1260541 15 my $self = shift @_;
16 if(blessed $self) {
17 return $self->__type_constraint->name;
18 } else {
19 return "$self";
20 }
4c2125a4 21 },
cf1a8bfa 22 '|' => sub {
686e5888 23
24 ## It's kind of ugly that we need to know about Union Types, but this
25 ## is needed for syntax compatibility. Maybe someday we'll all just do
26 ## Or[Str,Str,Int]
442e42ba 27
0d07f026 28 my @args = @_[0,1]; ## arg 3 is special, see the overload docs.
29 my @tc = grep {blessed $_} map {
30 blessed $_ ? $_ :
31 Moose::Util::TypeConstraints::find_or_parse_type_constraint($_)
3ade1c44 32 || __PACKAGE__->_throw_error( "$_ is not a type constraint")
0d07f026 33 } @args;
34
35 ( scalar @tc == scalar @args)
3ade1c44 36 || __PACKAGE__->_throw_error(
37 "one of your type constraints is bad. Passed: ". join(', ', @args) ." Got: ". join(', ', @tc));
0d07f026 38
39 ( scalar @tc >= 2 )
3ade1c44 40 || __PACKAGE__->_throw_error("You must pass in at least 2 type names to make a union");
442e42ba 41
bb5b7b28 42 my $union = Moose::Meta::TypeConstraint::Union->new(type_constraints=>\@tc);
43 return Moose::Util::TypeConstraints::register_type_constraint($union);
cf1a8bfa 44 },
1d9a68a6 45 fallback => 1,
46
4c2125a4 47);
48
49=head1 NAME
50
51MooseX::Types::TypeDecorator - More flexible access to a Type Constraint
52
53=head1 DESCRIPTION
54
55This is a decorator object that contains an underlying type constraint. We use
56this to control access to the type constraint and to add some features.
57
a706b0f2 58=head1 METHODS
4c2125a4 59
a706b0f2 60This class defines the following methods.
4c2125a4 61
a706b0f2 62=head2 new
4c2125a4 63
a706b0f2 64Old school instantiation
4c2125a4 65
66=cut
67
a706b0f2 68sub new {
475bbd1d 69 my $class = shift @_;
70 if(my $arg = shift @_) {
371efa05 71 if(blessed $arg && $arg->isa('Moose::Meta::TypeConstraint')) {
475bbd1d 72 return bless {'__type_constraint'=>$arg}, $class;
e7d06577 73 } elsif(
74 blessed $arg &&
75 $arg->isa('MooseX::Types::UndefinedType')
76 ) {
475bbd1d 77 ## stub in case we'll need to handle these types differently
78 return bless {'__type_constraint'=>$arg}, $class;
371efa05 79 } elsif(blessed $arg) {
3ade1c44 80 __PACKAGE__->_throw_error("Argument must be ->isa('Moose::Meta::TypeConstraint') or ->isa('MooseX::Types::UndefinedType'), not ". blessed $arg);
475bbd1d 81 } else {
3ade1c44 82 __PACKAGE__->_throw_error("Argument cannot be '$arg'");
475bbd1d 83 }
bb5b7b28 84 } else {
3ade1c44 85 __PACKAGE__->_throw_error("This method [new] requires a single argument.");
bb5b7b28 86 }
a706b0f2 87}
4c2125a4 88
5a9b6d38 89=head2 __type_constraint ($type_constraint)
4c2125a4 90
e088dd03 91Set/Get the type_constraint.
4c2125a4 92
93=cut
94
475bbd1d 95sub __type_constraint {
c1260541 96 my $self = shift @_;
371efa05 97 if(blessed $self) {
98 if(defined(my $tc = shift @_)) {
99 $self->{__type_constraint} = $tc;
100 }
101 return $self->{__type_constraint};
102 } else {
3ade1c44 103 __PACKAGE__->_throw_error('cannot call __type_constraint as a class method');
a706b0f2 104 }
a706b0f2 105}
4c2125a4 106
bb5b7b28 107=head2 isa
108
109handle $self->isa since AUTOLOAD can't.
110
111=cut
112
113sub isa {
371efa05 114 my ($self, $target) = @_;
bb5b7b28 115 if(defined $target) {
c1260541 116 if(blessed $self) {
117 return $self->__type_constraint->isa($target);
118 } else {
119 return;
120 }
bb5b7b28 121 } else {
122 return;
123 }
124}
125
3ade1c44 126
bb5b7b28 127=head2 can
128
129handle $self->can since AUTOLOAD can't.
130
131=cut
132
133sub can {
134 my ($self, $target) = @_;
135 if(defined $target) {
c1260541 136 if(blessed $self) {
137 return $self->__type_constraint->can($target);
138 } else {
139 return;
140 }
bb5b7b28 141 } else {
142 return;
143 }
144}
145
c1260541 146=head2 meta
147
148have meta examine the underlying type constraints
149
150=cut
151
152sub meta {
153 my $self = shift @_;
154 if(blessed $self) {
155 return $self->__type_constraint->meta;
156 }
157}
158
3ade1c44 159=head2 _throw_error
160
161properly delegate error messages
162
163=cut
164
165sub _throw_error {
166 shift;
167 require Moose;
168 unshift @_, 'Moose';
169 goto &Moose::throw_error;
170}
c1260541 171
a706b0f2 172=head2 DESTROY
4c2125a4 173
a706b0f2 174We might need it later
4c2125a4 175
a706b0f2 176=cut
4c2125a4 177
a706b0f2 178sub DESTROY {
179 return;
180}
4c2125a4 181
a706b0f2 182=head2 AUTOLOAD
4c2125a4 183
a706b0f2 184Delegate to the decorator targe
4c2125a4 185
a706b0f2 186=cut
4c2125a4 187
e088dd03 188sub AUTOLOAD {
077ac262 189
475bbd1d 190 my ($self, @args) = @_;
a706b0f2 191 my ($method) = (our $AUTOLOAD =~ /([^:]+)$/);
077ac262 192
193 ## We delegate with this method in an attempt to support a value of
194 ## __type_constraint which is also AUTOLOADing, in particular the class
195 ## MooseX::Types::UndefinedType which AUTOLOADs during autovivication.
196
197 my $return;
198
199 eval {
200 $return = $self->__type_constraint->$method(@args);
201 }; if($@) {
3ade1c44 202 __PACKAGE__->_throw_error($@);
475bbd1d 203 } else {
077ac262 204 return $return;
475bbd1d 205 }
a706b0f2 206}
4c2125a4 207
b55332a8 208=head1 AUTHOR
4c2125a4 209
b55332a8 210See L<MooseX::Types/AUTHOR>.
4c2125a4 211
212=head1 LICENSE
213
214This program is free software; you can redistribute it and/or modify
215it under the same terms as perl itself.
216
217=cut
218
2191;