364faa29ca789df2ff87448a3f4294d5aa92d974
[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 warnings;
11 #use strict;
12
13 use Moose::Util::TypeConstraints;
14 use MooseX::Types::TypeDecorator;
15 use MooseX::Types::Base             ();
16 use MooseX::Types::Util             qw( filter_tags );
17 use MooseX::Types::UndefinedType;
18 use Carp::Clan                      qw( ^MooseX::Types );
19
20 use namespace::clean -except => [qw( meta )];
21
22 our $VERSION = 0.06;
23
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 'Int';
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.  Please note the containing '(...)'
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   1;
77
78 =head2 Usage
79
80   package Foo;
81   use Moose;
82   use MyLibrary qw( PositiveInt NegativeInt );
83
84   # use the exported constants as type names
85   has 'bar',
86       isa    => PositiveInt,
87       is     => 'rw';
88   has 'baz',
89       isa    => NegativeInt,
90       is     => 'rw';
91
92   sub quux {
93       my ($self, $value);
94
95       # test the value
96       print "positive\n" if is_PositiveInt($value);
97       print "negative\n" if is_NegativeInt($value);
98
99       # coerce the value, NegativeInt doesn't have a coercion
100       # helper, since it didn't define any coercions.
101       $value = to_PositiveInt($value) or die "Cannot coerce";
102   }
103
104   1;
105
106 =head1 DESCRIPTION
107
108 The types provided with L<Moose> are by design global. This package helps
109 you to organise and selectively import your own and the built-in types in
110 libraries. As a nice side effect, it catches typos at compile-time too.
111
112 However, the main reason for this module is to provide an easy way to not
113 have conflicts with your type names, since the internal fully qualified
114 names of the types will be prefixed with the library's name.
115
116 This module will also provide you with some helper functions to make it 
117 easier to use Moose types in your code.
118
119 =head1 TYPE HANDLER FUNCTIONS
120
121 =head2 $type
122
123 A constant with the name of your type. It contains the type's fully
124 qualified name. Takes no value, as all constants.
125
126 =head2 is_$type
127
128 This handler takes a value and tests if it is a valid value for this
129 C<$type>. It will return true or false.
130
131 =head2 to_$type
132
133 A handler that will take a value and coerce it into the C<$type>. It will
134 return a false value if the type could not be coerced.
135
136 B<Important Note>: This handler will only be exported for types that can
137 do type coercion. This has the advantage that a coercion to a type that
138 cannot hasn't defined any coercions will lead to a compile-time error.
139
140 =head1 LIBRARY DEFINITION
141
142 A MooseX::Types is just a normal Perl module. Unlike Moose 
143 itself, it does not install C<use strict> and C<use warnings> in your
144 class by default, so this is up to you.
145
146 The only thing a library is required to do is
147
148   use MooseX::Types -declare => \@types;
149
150 with C<@types> being a list of types you wish to define in this library.
151 This line will install a proper base class in your package as well as the
152 full set of L<handlers|/"TYPE HANDLER FUNCTIONS"> for your declared 
153 types. It will then hand control over to L<Moose::Util::TypeConstraints>'
154 C<import> method to export the functions you will need to declare your
155 types.
156
157 If you want to use Moose' built-in types (e.g. for subtyping) you will 
158 want to 
159
160   use MooseX::Types::Moose @types;
161
162 to import the helpers from the shipped L<MooseX::Types::Moose>
163 library which can export all types that come with Moose.
164
165 You will have to define coercions for your types or your library won't
166 export a L</to_$type> coercion helper for it.
167
168 Note that you currently cannot define types containing C<::>, since 
169 exporting would be a problem.
170
171 You also don't need to use C<warnings> and C<strict>, since the
172 definition of a library automatically exports those.
173
174 =head1 LIBRARY USAGE
175
176 You can import the L<"type helpers"|/"TYPE HANDLER FUNCTIONS"> of a
177 library by C<use>ing it with a list of types to import as arguments. If
178 you want all of them, use the C<:all> tag. For example:
179
180   use MyLibrary      ':all';
181   use MyOtherLibrary qw( TypeA TypeB );
182
183 MooseX::Types comes with a library of Moose' built-in types called
184 L<MooseX::Types::Moose>.
185
186 The exporting mechanism is, since version 0.5, implemented via a wrapper
187 around L<Sub::Exporter>. This means you can do something like this:
188
189   use MyLibrary TypeA => { -as => 'MyTypeA' },
190                 TypeB => { -as => 'MyTypeB' };
191
192 =head1 WRAPPING A LIBRARY
193
194 You can define your own wrapper subclasses to manipulate the behaviour
195 of a set of library exports. Here is an example:
196
197   package MyWrapper;
198   use strict;
199   use Class::C3;
200   use base 'MooseX::Types::Wrapper';
201
202   sub coercion_export_generator {
203       my $class = shift;
204       my $code = $class->next::method(@_);
205       return sub {
206           my $value = $code->(@_);
207           warn "Coercion returned undef!"
208               unless defined $value;
209           return $value;
210       };
211   }
212
213   1;
214
215 This class wraps the coercion generator (e.g., C<to_Int()>) and warns
216 if a coercion returned an undefined value. You can wrap any library
217 with this:
218
219   package Foo;
220   use strict;
221   use MyWrapper MyLibrary => [qw( Foo Bar )],
222                 Moose     => [qw( Str Int )];
223
224   ...
225   1;
226
227 The C<Moose> library name is a special shortcut for 
228 L<MooseX::Types::Moose>.
229
230 =head2 Generator methods you can overload
231
232 =over 4
233
234 =item type_export_generator( $short, $full )
235
236 Creates a closure returning the type's L<Moose::Meta::TypeConstraint> 
237 object. 
238
239 =item check_export_generator( $short, $full, $undef_message )
240
241 This creates the closure used to test if a value is valid for this type.
242
243 =item coercion_export_generator( $short, $full, $undef_message )
244
245 This is the closure that's doing coercions.
246
247 =back
248
249 =head2 Provided Parameters
250
251 =over 4
252
253 =item $short
254
255 The short, exported name of the type.
256
257 =item $full
258
259 The fully qualified name of this type as L<Moose> knows it.
260
261 =item $undef_message
262
263 A message that will be thrown when type functionality is used but the
264 type does not yet exist.
265
266 =back
267
268 =head1 NOTES REGARDING PARAMETERIZED CONSTRAINTS
269
270 L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
271 which generally allows you to easily create types with parameters such as:
272
273     subtype ParameterType,
274       as (ArrayRef[Int]);
275
276 However, due to an outstanding issue you will need to wrap the parameterized
277 type inside parenthesis, as in the example above.  Hopefully this limitation
278 will be lifted in a future version of this module.
279
280 If you are using paramterized types in the options section of an attribute
281 declaration, the parenthesis are not needed:
282
283     use Moose;
284     use MooseX::Types::Moose qw(HashRef Int);
285     
286     has 'attr' => (isa=>HashRef[Str]);
287
288 =head1 NOTES REGARDING TYPE UNIONS
289
290 L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
291 which generally allows you to easily create union types:
292
293   subtype StrOrArrayRef,
294     as Str|ArrayRef;    
295
296 As with parameterized constrains, this overloading extends to modules using the
297 types you define in a type library.
298
299     use Moose;
300     use MooseX::Types::Moose qw(HashRef Int);
301     
302     has 'attr' => (isa=>HashRef|Int);
303
304 And everything should just work as you'd think.
305     
306 =head1 METHODS
307
308 =head2 import
309
310 Installs the L<MooseX::Types::Base> class into the caller and 
311 exports types according to the specification described in 
312 L</"LIBRARY DEFINITION">. This will continue to 
313 L<Moose::Util::TypeConstraints>' C<import> method to export helper
314 functions you will need to declare your types.
315
316 =cut
317
318 sub import {
319     my ($class, %args) = @_;
320     my  $callee = caller;
321
322     # everyone should want this
323     strict->import;
324     warnings->import;
325
326     # inject base class into new library
327     {   no strict 'refs';
328         unshift @{ $callee . '::ISA' }, 'MooseX::Types::Base';
329     }
330
331     # generate predeclared type helpers
332     if (my @orig_declare = @{ $args{ -declare } || [] }) {
333         my ($tags, $declare) = filter_tags @orig_declare;
334         my @to_export;
335
336         for my $type (@$declare) {
337
338             croak "Cannot create a type containing '::' ($type) at the moment"
339                 if $type =~ /::/;
340
341             # add type to library and remember to export
342             $callee->add_type($type);
343             push @to_export, $type;
344         }
345
346         $callee->import({ -full => 1, -into => $callee }, @to_export);
347     }
348
349     # run type constraints import
350     return Moose::Util::TypeConstraints->import({ into => $callee });
351 }
352
353 =head2 type_export_generator
354
355 Generate a type export, e.g. C<Int()>. This will return either a
356 L<Moose::Meta::TypeConstraint> object, or alternatively a
357 L<MooseX::Types::UndefinedType> object if the type was not
358 yet defined.
359
360 =cut
361
362 sub type_export_generator {
363     my ($class, $type, $name) = @_;
364     return sub {
365         my $type_constraint;
366         if(defined(my $params = shift @_)) {
367             if(ref $params eq 'ARRAY') {
368                 $type_constraint = $class->create_arged_type_constraint($name, @$params);
369             } else {
370                 croak 'Arguments must be an ArrayRef, not '. ref $params;
371             }
372         } else {
373             $type_constraint = $class->create_base_type_constraint($name);
374         }
375         $type_constraint = defined($type_constraint) ? $type_constraint
376          : MooseX::Types::UndefinedType->new($name);
377          
378         return $class->create_type_decorator($type_constraint);
379         
380     };
381 }
382
383 =head2 create_arged_type_constraint ($name, @args)
384
385 Given a String $name with @args find the matching typeconstraint.
386
387 =cut
388
389 sub create_arged_type_constraint {
390     my ($class, $name, @args) = @_;
391     my $type_constraint = Moose::Util::TypeConstraints::find_or_create_type_constraint($name);
392         return $type_constraint->parameterize(@args)
393 }
394
395 =head2 create_base_type_constraint ($name)
396
397 Given a String $name, find the matching typeconstraint.
398
399 =cut
400
401 sub create_base_type_constraint {
402     my ($class, $name) = @_;
403     return find_type_constraint($name);
404 }
405
406 =head2 create_type_decorator ($type_constraint)
407
408 Given a $type_constraint, return a lightweight L<MooseX::Types::TypeDecorator>
409 instance.
410
411 =cut
412
413 sub create_type_decorator {
414     my ($class, $type_constraint) = @_;
415     return MooseX::Types::TypeDecorator->new($type_constraint);
416 }
417
418 =head2 coercion_export_generator
419
420 This generates a coercion handler function, e.g. C<to_Int($value)>. 
421
422 =cut
423
424 sub coercion_export_generator {
425     my ($class, $type, $full, $undef_msg) = @_;
426     return sub {
427         my ($value) = @_;
428
429         # we need a type object
430         my $tobj = find_type_constraint($full) or croak $undef_msg;
431         my $return = $tobj->coerce($value);
432
433         # non-successful coercion returns false
434         return unless $tobj->check($return);
435
436         return $return;
437     }
438 }
439
440 =head2 check_export_generator
441
442 Generates a constraint check closure, e.g. C<is_Int($value)>.
443
444 =cut
445
446 sub check_export_generator {
447     my ($class, $type, $full, $undef_msg) = @_;
448     return sub {
449         my ($value) = @_;
450
451         # we need a type object
452         my $tobj = find_type_constraint($full) or croak $undef_msg;
453
454         return $tobj->check($value);
455     }
456 }
457
458 =head1 CAVEATS
459
460 A library makes the types quasi-unique by prefixing their names with (by
461 default) the library package name. If you're only using the type handler
462 functions provided by MooseX::Types, you shouldn't ever have to use
463 a type's actual full name.
464
465 =head1 SEE ALSO
466
467 L<Moose>, 
468 L<Moose::Util::TypeConstraints>, 
469 L<MooseX::Types::Moose>,
470 L<Sub::Exporter>
471
472 =head1 AUTHOR AND COPYRIGHT
473
474 Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
475 the C<#moose> cabal on C<irc.perl.org>.
476
477 Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>.
478
479 =head1 LICENSE
480
481 This program is free software; you can redistribute it and/or modify
482 it under the same terms as perl itself.
483
484 =cut
485
486 1;