061ad2352319c5d1d0c56487b62d1f8401b137c9
[gitmo/MooseX-Types.git] / lib / MooseX / Types.pm
1 package MooseX::Types;
2 use Moose;
3
4 =head1 NAME
5
6 MooseX::Types - Organise your Moose types in libraries
7
8 =cut
9
10 use Moose::Util::TypeConstraints;
11 use MooseX::Types::TypeDecorator;
12 use MooseX::Types::Base               ();
13 use MooseX::Types::Util               qw( filter_tags );
14 use MooseX::Types::UndefinedType;
15 use MooseX::Types::CheckedUtilExports ();
16 use Carp::Clan                        qw( ^MooseX::Types );
17 use Sub::Name;
18 use Scalar::Util                      'reftype';
19
20 use namespace::clean -except => [qw( meta )];
21
22 use 5.008;
23 our $VERSION = '0.11';
24 my $UndefMsg = q{Action for type '%s' not yet defined in library '%s'};
25
26 =head1 SYNOPSIS
27
28 =head2 Library Definition
29
30   package MyLibrary;
31
32   # predeclare our own types
33   use MooseX::Types 
34     -declare => [qw(
35         PositiveInt NegativeInt
36         ArrayRefOfPositiveInt ArrayRefOfAtLeastThreeNegativeInts
37         LotsOfInnerConstraints StrOrArrayRef
38     )];
39
40   # import builtin types
41   use MooseX::Types::Moose qw/Int HashRef/;
42
43   # type definition.
44   subtype PositiveInt, 
45       as Int, 
46       where { $_ > 0 },
47       message { "Int is not larger than 0" };
48   
49   subtype NegativeInt,
50       as Int,
51       where { $_ < 0 },
52       message { "Int is not smaller than 0" };
53
54   # type coercion
55   coerce PositiveInt,
56       from Int,
57           via { 1 };
58
59   # with parameterized constraints.
60   
61   subtype ArrayRefOfPositiveInt,
62     as ArrayRef[PositiveInt];
63     
64   subtype ArrayRefOfAtLeastThreeNegativeInts,
65     as ArrayRef[NegativeInt],
66     where { scalar(@$_) > 2 };
67
68   subtype LotsOfInnerConstraints,
69     as ArrayRef[ArrayRef[HashRef[Int]]];
70     
71   # with TypeConstraint Unions
72   
73   subtype StrOrArrayRef,
74     as Str|ArrayRef;
75
76   class_type 'DateTime';
77
78   coerce 'DateTime',
79     from HashRef,
80     via { DateTime->new(%$_) };
81
82   1;
83
84 =head2 Usage
85
86   package Foo;
87   use Moose;
88   use MyLibrary qw( PositiveInt NegativeInt );
89
90   # use the exported constants as type names
91   has 'bar',
92       isa    => PositiveInt,
93       is     => 'rw';
94   has 'baz',
95       isa    => NegativeInt,
96       is     => 'rw';
97
98   sub quux {
99       my ($self, $value);
100
101       # test the value
102       print "positive\n" if is_PositiveInt($value);
103       print "negative\n" if is_NegativeInt($value);
104
105       # coerce the value, NegativeInt doesn't have a coercion
106       # helper, since it didn't define any coercions.
107       $value = to_PositiveInt($value) or die "Cannot coerce";
108   }
109
110   1;
111
112 =head1 DESCRIPTION
113
114 The types provided with L<Moose> are by design global. This package helps
115 you to organise and selectively import your own and the built-in types in
116 libraries. As a nice side effect, it catches typos at compile-time too.
117
118 However, the main reason for this module is to provide an easy way to not
119 have conflicts with your type names, since the internal fully qualified
120 names of the types will be prefixed with the library's name.
121
122 This module will also provide you with some helper functions to make it 
123 easier to use Moose types in your code.
124
125 String type names will produce a syntax error, unless it's for a C<class_type>
126 or C<role_type> declared within the library.
127
128 =head1 TYPE HANDLER FUNCTIONS
129
130 =head2 $type
131
132 A constant with the name of your type. It contains the type's fully
133 qualified name. Takes no value, as all constants.
134
135 =head2 is_$type
136
137 This handler takes a value and tests if it is a valid value for this
138 C<$type>. It will return true or false.
139
140 =head2 to_$type
141
142 A handler that will take a value and coerce it into the C<$type>. It will
143 return a false value if the type could not be coerced.
144
145 B<Important Note>: This handler will only be exported for types that can
146 do type coercion. This has the advantage that a coercion to a type that
147 cannot hasn't defined any coercions will lead to a compile-time error.
148
149 =head1 LIBRARY DEFINITION
150
151 A MooseX::Types is just a normal Perl module. Unlike Moose 
152 itself, it does not install C<use strict> and C<use warnings> in your
153 class by default, so this is up to you.
154
155 The only thing a library is required to do is
156
157   use MooseX::Types -declare => \@types;
158
159 with C<@types> being a list of types you wish to define in this library.
160 This line will install a proper base class in your package as well as the
161 full set of L<handlers|/"TYPE HANDLER FUNCTIONS"> for your declared 
162 types. It will then hand control over to L<Moose::Util::TypeConstraints>'
163 C<import> method to export the functions you will need to declare your
164 types.
165
166 If you want to use Moose' built-in types (e.g. for subtyping) you will 
167 want to 
168
169   use MooseX::Types::Moose @types;
170
171 to import the helpers from the shipped L<MooseX::Types::Moose>
172 library which can export all types that come with Moose.
173
174 You will have to define coercions for your types or your library won't
175 export a L</to_$type> coercion helper for it.
176
177 Note that you currently cannot define types containing C<::>, since 
178 exporting would be a problem.
179
180 You also don't need to use C<warnings> and C<strict>, since the
181 definition of a library automatically exports those.
182
183 =head1 LIBRARY USAGE
184
185 You can import the L<"type helpers"|/"TYPE HANDLER FUNCTIONS"> of a
186 library by C<use>ing it with a list of types to import as arguments. If
187 you want all of them, use the C<:all> tag. For example:
188
189   use MyLibrary      ':all';
190   use MyOtherLibrary qw( TypeA TypeB );
191
192 MooseX::Types comes with a library of Moose' built-in types called
193 L<MooseX::Types::Moose>.
194
195 The exporting mechanism is, since version 0.5, implemented via a wrapper
196 around L<Sub::Exporter>. This means you can do something like this:
197
198   use MyLibrary TypeA => { -as => 'MyTypeA' },
199                 TypeB => { -as => 'MyTypeB' };
200
201 =head1 WRAPPING A LIBRARY
202
203 You can define your own wrapper subclasses to manipulate the behaviour
204 of a set of library exports. Here is an example:
205
206   package MyWrapper;
207   use strict;
208   use Class::C3;
209   use base 'MooseX::Types::Wrapper';
210
211   sub coercion_export_generator {
212       my $class = shift;
213       my $code = $class->next::method(@_);
214       return sub {
215           my $value = $code->(@_);
216           warn "Coercion returned undef!"
217               unless defined $value;
218           return $value;
219       };
220   }
221
222   1;
223
224 This class wraps the coercion generator (e.g., C<to_Int()>) and warns
225 if a coercion returned an undefined value. You can wrap any library
226 with this:
227
228   package Foo;
229   use strict;
230   use MyWrapper MyLibrary => [qw( Foo Bar )],
231                 Moose     => [qw( Str Int )];
232
233   ...
234   1;
235
236 The C<Moose> library name is a special shortcut for 
237 L<MooseX::Types::Moose>.
238
239 =head2 Generator methods you can overload
240
241 =over 4
242
243 =item type_export_generator( $short, $full )
244
245 Creates a closure returning the type's L<Moose::Meta::TypeConstraint> 
246 object. 
247
248 =item check_export_generator( $short, $full, $undef_message )
249
250 This creates the closure used to test if a value is valid for this type.
251
252 =item coercion_export_generator( $short, $full, $undef_message )
253
254 This is the closure that's doing coercions.
255
256 =back
257
258 =head2 Provided Parameters
259
260 =over 4
261
262 =item $short
263
264 The short, exported name of the type.
265
266 =item $full
267
268 The fully qualified name of this type as L<Moose> knows it.
269
270 =item $undef_message
271
272 A message that will be thrown when type functionality is used but the
273 type does not yet exist.
274
275 =back
276
277 =head1 RECURSIVE SUBTYPES
278
279 As of version 0.08, L<Moose::Types> has experimental support for Recursive
280 subtypes.  This will allow:
281
282     subtype Tree() => as HashRef[Str|Tree];
283
284 Which validates things like:
285
286     {key=>'value'};
287     {key=>{subkey1=>'value', subkey2=>'value'}}
288     
289 And so on.  This feature is new and there may be lurking bugs so don't be afraid
290 to hunt me down with patches and test cases if you have trouble.
291
292 =head1 NOTES REGARDING TYPE UNIONS
293
294 L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
295 which generally allows you to easily create union types:
296
297   subtype StrOrArrayRef,
298     as Str|ArrayRef;    
299
300 As with parameterized constrains, this overloading extends to modules using the
301 types you define in a type library.
302
303     use Moose;
304     use MooseX::Types::Moose qw(HashRef Int);
305     
306     has 'attr' => (isa=>HashRef|Int);
307
308 And everything should just work as you'd think.
309
310 =head1 METHODS
311
312 =head2 import
313
314 Installs the L<MooseX::Types::Base> class into the caller and 
315 exports types according to the specification described in 
316 L</"LIBRARY DEFINITION">. This will continue to 
317 L<Moose::Util::TypeConstraints>' C<import> method to export helper
318 functions you will need to declare your types.
319
320 =cut
321
322 sub import {
323     my ($class, %args) = @_;
324     my  $callee = caller;
325
326     # everyone should want this
327     strict->import;
328     warnings->import;
329
330     # inject base class into new library
331     {   no strict 'refs';
332         unshift @{ $callee . '::ISA' }, 'MooseX::Types::Base';
333     }
334
335     # generate predeclared type helpers
336     if (my @orig_declare = @{ $args{ -declare } || [] }) {
337         my ($tags, $declare) = filter_tags @orig_declare;
338         my @to_export;
339
340         for my $type (@$declare) {
341
342             croak "Cannot create a type containing '::' ($type) at the moment"
343                 if $type =~ /::/;
344
345             # add type to library and remember to export
346             $callee->add_type($type);
347             push @to_export, $type;
348         }
349
350         $callee->import({ -full => 1, -into => $callee }, @to_export);
351     }
352
353     # run type constraints import
354     Moose::Util::TypeConstraints->import({ into => $callee });
355
356     # override some with versions that check for syntax errors
357     MooseX::Types::CheckedUtilExports->import({ into => $callee });
358
359     1;
360 }
361
362 =head2 type_export_generator
363
364 Generate a type export, e.g. C<Int()>. This will return either a
365 L<Moose::Meta::TypeConstraint> object, or alternatively a
366 L<MooseX::Types::UndefinedType> object if the type was not
367 yet defined.
368
369 =cut
370
371 sub type_export_generator {
372     my ($class, $type, $name) = @_;
373     
374     ## Return an anonymous subroutine that will generate the proxied type
375     ## constraint for you.
376     
377     return subname $name => sub {
378         my $type_constraint = $class->create_base_type_constraint($name);
379
380         if(defined(my $params = shift @_)) {
381             ## We currently only allow a TC to accept a single, ArrayRef
382             ## parameter, as in HashRef[Int], where [Int] is what's inside the
383             ## ArrayRef passed.
384             if(reftype $params eq 'ARRAY') {
385                 $type_constraint = $class->create_arged_type_constraint($name, @$params);
386             } elsif(!defined $type_constraint) {
387                 croak "Syntax error in type definition (did you forget a comma"
388                     . " after $type?)";
389             } else {
390                 croak "Argument must be an ArrayRef to create a parameterized "
391                     . "type, Eg.: ${type}[Int]. Got: ".ref($params)."."
392             }
393         }
394
395         $type_constraint = defined($type_constraint) ? $type_constraint
396          : MooseX::Types::UndefinedType->new($name);
397          
398         my $type_decorator = $class->create_type_decorator($type_constraint);
399         
400         ## If there are additional args, that means it's probably stuff that
401         ## needs to be returned to the subtype.  Not an ideal solution here but
402         ## doesn't seem to cause trouble.
403         
404         if(@_) {
405             return ($type_decorator, @_);
406         } else {
407             return $type_decorator;
408         }
409     };
410 }
411
412 =head2 create_arged_type_constraint ($name, @args)
413
414 Given a String $name with @args find the matching typeconstraint and parameterize
415 it with @args.
416
417 =cut
418
419 sub create_arged_type_constraint {
420     my ($class, $name, @args) = @_;  
421     my $type_constraint = Moose::Util::TypeConstraints::find_or_create_type_constraint("$name");
422         return $type_constraint->parameterize(@args);
423 }
424
425 =head2 create_base_type_constraint ($name)
426
427 Given a String $name, find the matching typeconstraint.
428
429 =cut
430
431 sub create_base_type_constraint {
432     my ($class, $name) = @_;
433     return find_type_constraint($name);
434 }
435
436 =head2 create_type_decorator ($type_constraint)
437
438 Given a $type_constraint, return a lightweight L<MooseX::Types::TypeDecorator>
439 instance.
440
441 =cut
442
443 sub create_type_decorator {
444     my ($class, $type_constraint) = @_;
445     return MooseX::Types::TypeDecorator->new($type_constraint);
446 }
447
448 =head2 coercion_export_generator
449
450 This generates a coercion handler function, e.g. C<to_Int($value)>. 
451
452 =cut
453
454 sub coercion_export_generator {
455     my ($class, $type, $full, $undef_msg) = @_;
456     return sub {
457         my ($value) = @_;
458
459         # we need a type object
460         my $tobj = find_type_constraint($full) or croak $undef_msg;
461         my $return = $tobj->coerce($value);
462
463         # non-successful coercion returns false
464         return unless $tobj->check($return);
465
466         return $return;
467     }
468 }
469
470 =head2 check_export_generator
471
472 Generates a constraint check closure, e.g. C<is_Int($value)>.
473
474 =cut
475
476 sub check_export_generator {
477     my ($class, $type, $full, $undef_msg) = @_;
478     return sub {
479         my ($value) = @_;
480
481         # we need a type object
482         my $tobj = find_type_constraint($full) or croak $undef_msg;
483
484         return $tobj->check($value);
485     }
486 }
487
488 =head1 CAVEATS
489
490 The following are lists of gotcha's and their workarounds for developers coming
491 from the standard string based type constraint names
492
493 =head2 Uniqueness
494
495 A library makes the types quasi-unique by prefixing their names with (by
496 default) the library package name. If you're only using the type handler
497 functions provided by MooseX::Types, you shouldn't ever have to use
498 a type's actual full name.
499
500 =head2 Argument separation ('=>' versus ',')
501
502 The Perlop manpage has this to say about the '=>' operator: "The => operator is
503 a synonym for the comma, but forces any word (consisting entirely of word
504 characters) to its left to be interpreted as a string (as of 5.001). This
505 includes words that might otherwise be considered a constant or function call."
506
507 Due to this stringification, the following will NOT work as you might think:
508
509   subtype StrOrArrayRef => as Str|ArrayRef;
510   
511 The 'StrOrArrayRef' will have it's stringification activated this causes the
512 subtype to not be created.  Since the bareword type constraints are not strings
513 you really should not try to treat them that way.  You will have to use the ','
514 operator instead.  The author's of this package realize that all the L<Moose>
515 documention and examples nearly uniformly use the '=>' version of the comma
516 operator and this could be an issue if you are converting code.
517
518 Patches welcome for discussion.
519
520 =head2 Compatibility with Sub::Exporter
521
522 If you want to use L<Sub::Exporter> with a Type Library, you need to make sure
523 you export all the type constraints declared AS WELL AS any additional export
524 targets. For example if you do:
525
526     package TypeAndSubExporter; {
527         
528         use MooseX::Types::Moose qw(Str);
529         use MooseX::Types -declare => [qw(MyStr)];
530         use Sub::Exporter -setup => { exports => [ qw(something) ] };
531         
532         subtype MyStr,
533          as Str;
534          
535         sub something {
536             return 1;
537         }    
538         
539     } 1;
540     
541     package Foo; {
542         use TypeAndSubExporter qw(MyStr);
543     } 1;
544
545 You'll get a '"MyStr" is not exported by the TypeAndSubExporter module' error.
546 Upi can workaround by:
547
548         - use Sub::Exporter -setup => { exports => [ qw(something) ] };
549         + use Sub::Exporter -setup => { exports => [ qw(something MyStr) ] };
550
551 This is a workaround and I am exploring how to make these modules work better
552 together.  I realize this workaround will lead a lot of duplication in your
553 export declarations and will be onerous for large type libraries.  Patches and
554 detailed test cases welcome. See the tests directory for a start on this.
555     
556 =head1 SEE ALSO
557
558 L<Moose>, 
559 L<Moose::Util::TypeConstraints>, 
560 L<MooseX::Types::Moose>,
561 L<Sub::Exporter>
562
563 =head1 AUTHOR AND COPYRIGHT
564
565 Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
566 the C<#moose> cabal on C<irc.perl.org>.
567
568 Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>.
569
570 =head1 LICENSE
571
572 This program is free software; you can redistribute it and/or modify
573 it under the same terms as perl itself.
574
575 =cut
576
577 1;