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