use strict;
use warnings;
+
use Carp::Clan qw( ^MooseX::Types );
-use Moose::Util::TypeConstraints;
+use Moose::Util::TypeConstraints ();
use Moose::Meta::TypeConstraint::Union;
+use Scalar::Util qw(blessed);
use overload(
'""' => sub {
- shift->type_constraint->name;
+ my $self = shift @_;
+ if(blessed $self) {
+ return $self->__type_constraint->name;
+ } else {
+ return "$self";
+ }
},
'|' => sub {
- my @tc = grep {ref $_} @_;
+
+ ## It's kind of ugly that we need to know about Union Types, but this
+ ## is needed for syntax compatibility. Maybe someday we'll all just do
+ ## Or[Str,Str,Int]
+
+ my @tc = map {
+ blessed $_ ? $_ :
+ Moose::Util::TypeConstraints::find_or_parse_type_constraint($_)
+ } @_;
+
my $union = Moose::Meta::TypeConstraint::Union->new(type_constraints=>\@tc);
return Moose::Util::TypeConstraints::register_type_constraint($union);
},
+ fallback => 1,
+
);
=head1 NAME
=cut
sub new {
- my ($class, %args) = @_;
- if(
- $args{type_constraint} && ref($args{type_constraint}) &&
- ($args{type_constraint}->isa('Moose::Meta::TypeConstraint') ||
- $args{type_constraint}->isa('MooseX::Types::UndefinedType'))
- ) {
- return bless \%args, $class;
+ my $class = shift @_;
+ if(my $arg = shift @_) {
+ if(blessed $arg && $arg->isa('Moose::Meta::TypeConstraint')) {
+ return bless {'__type_constraint'=>$arg}, $class;
+ } elsif(
+ blessed $arg &&
+ $arg->isa('MooseX::Types::UndefinedType')
+ ) {
+ ## stub in case we'll need to handle these types differently
+ return bless {'__type_constraint'=>$arg}, $class;
+ } elsif(blessed $arg) {
+ croak "Argument must be ->isa('Moose::Meta::TypeConstraint') or ->isa('MooseX::Types::UndefinedType'), not ". blessed $arg;
+ } else {
+ croak "Argument cannot be '$arg'";
+ }
} else {
- croak "The argument 'type_constraint' is not valid.";
+ croak "This method [new] requires a single argument.";
}
-
}
-=head type_constraint ($type_constraint)
+=head2 __type_constraint ($type_constraint)
Set/Get the type_constraint.
=cut
-sub type_constraint {
- my $self = shift @_;
- if(defined(my $tc = shift @_)) {
- $self->{type_constraint} = $tc;
+sub __type_constraint {
+ my $self = shift @_;
+ if(blessed $self) {
+ if(defined(my $tc = shift @_)) {
+ $self->{__type_constraint} = $tc;
+ }
+ return $self->{__type_constraint};
+ } else {
+ croak 'cannot call __type_constraint as a class method';
}
- return $self->{type_constraint};
}
=head2 isa
=cut
sub isa {
- my ($self, $target) = @_;
+ my ($self, $target) = @_;
if(defined $target) {
- my $isa = $self->type_constraint->isa($target);
- return $isa;
+ if(blessed $self) {
+ return $self->__type_constraint->isa($target);
+ } else {
+ return;
+ }
} else {
return;
}
sub can {
my ($self, $target) = @_;
if(defined $target) {
- my $can = $self->type_constraint->can($target);
- return $can;
+ if(blessed $self) {
+ return $self->__type_constraint->can($target);
+ } else {
+ return;
+ }
} else {
return;
}
}
+=head2 meta
+
+have meta examine the underlying type constraints
+
+=cut
+
+sub meta {
+ my $self = shift @_;
+ if(blessed $self) {
+ return $self->__type_constraint->meta;
+ }
+}
+
+
=head2 DESTROY
We might need it later
=cut
sub AUTOLOAD {
+
+ my ($self, @args) = @_;
my ($method) = (our $AUTOLOAD =~ /([^:]+)$/);
- return shift->type_constraint->$method(@_);
+
+ ## We delegate with this method in an attempt to support a value of
+ ## __type_constraint which is also AUTOLOADing, in particular the class
+ ## MooseX::Types::UndefinedType which AUTOLOADs during autovivication.
+
+ my $return;
+
+ eval {
+ $return = $self->__type_constraint->$method(@args);
+ }; if($@) {
+ croak $@;
+ } else {
+ return $return;
+ }
}
=head1 AUTHOR AND COPYRIGHT