c93591fe2815bc657a222423c41586825d0b7251
[gitmo/MooseX-Types.git] / lib / MooseX / Types.pm
1 package MooseX::Types;
2
3 =head1 NAME
4
5 MooseX::Types - Organise your Moose types in libraries
6
7 =cut
8
9 #use warnings;
10 #use strict;
11
12 use Moose::Util::TypeConstraints;
13 use MooseX::Types::Base             ();
14 use MooseX::Types::Util             qw( filter_tags );
15 use MooseX::Types::UndefinedType;
16 use Sub::Install                    qw( install_sub );
17 use Carp                            qw( croak );
18 use Moose;
19
20 use namespace::clean -except => [qw( meta )];
21
22 our $VERSION = 0.05;
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( PositiveInt NegativeInt )];
35
36   # import builtin types
37   use MooseX::Types::Moose 'Int';
38
39   # type definition
40   subtype PositiveInt, 
41       as Int, 
42       where { $_ > 0 },
43       message { "Int is not larger than 0" };
44   
45   subtype NegativeInt,
46       as Int,
47       where { $_ < 0 },
48       message { "Int is not smaller than 0" };
49
50   # type coercion
51   coerce PositiveInt,
52       from Int,
53           via { 1 };
54
55   1;
56
57 =head2 Usage
58
59   package Foo;
60   use Moose;
61   use MyLibrary qw( PositiveInt NegativeInt );
62
63   # use the exported constants as type names
64   has 'bar',
65       isa    => PositiveInt,
66       is     => 'rw';
67   has 'baz',
68       isa    => NegativeInt,
69       is     => 'rw';
70
71   sub quux {
72       my ($self, $value);
73
74       # test the value
75       print "positive\n" if is_PositiveInt($value);
76       print "negative\n" if is_NegativeInt($value);
77
78       # coerce the value, NegativeInt doesn't have a coercion
79       # helper, since it didn't define any coercions.
80       $value = to_PositiveInt($value) or die "Cannot coerce";
81   }
82
83   1;
84
85 =head1 DESCRIPTION
86
87 The types provided with L<Moose> are by design global. This package helps
88 you to organise and selectively import your own and the built-in types in
89 libraries. As a nice side effect, it catches typos at compile-time too.
90
91 However, the main reason for this module is to provide an easy way to not
92 have conflicts with your type names, since the internal fully qualified
93 names of the types will be prefixed with the library's name.
94
95 This module will also provide you with some helper functions to make it 
96 easier to use Moose types in your code.
97
98 =head1 TYPE HANDLER FUNCTIONS
99
100 =head2 $type
101
102 A constant with the name of your type. It contains the type's fully
103 qualified name. Takes no value, as all constants.
104
105 =head2 is_$type
106
107 This handler takes a value and tests if it is a valid value for this
108 C<$type>. It will return true or false.
109
110 =head2 to_$type
111
112 A handler that will take a value and coerce it into the C<$type>. It will
113 return a false value if the type could not be coerced.
114
115 B<Important Note>: This handler will only be exported for types that can
116 do type coercion. This has the advantage that a coercion to a type that
117 cannot hasn't defined any coercions will lead to a compile-time error.
118
119 =head1 LIBRARY DEFINITION
120
121 A MooseX::Types is just a normal Perl module. Unlike Moose 
122 itself, it does not install C<use strict> and C<use warnings> in your
123 class by default, so this is up to you.
124
125 The only thing a library is required to do is
126
127   use MooseX::Types -declare => \@types;
128
129 with C<@types> being a list of types you wish to define in this library.
130 This line will install a proper base class in your package as well as the
131 full set of L<handlers|/"TYPE HANDLER FUNCTIONS"> for your declared 
132 types. It will then hand control over to L<Moose::Util::TypeConstraints>'
133 C<import> method to export the functions you will need to declare your
134 types.
135
136 If you want to use Moose' built-in types (e.g. for subtyping) you will 
137 want to 
138
139   use MooseX::Types::Moose @types;
140
141 to import the helpers from the shipped L<MooseX::Types::Moose>
142 library which can export all types that come with Moose.
143
144 You will have to define coercions for your types or your library won't
145 export a L</to_$type> coercion helper for it.
146
147 Note that you currently cannot define types containing C<::>, since 
148 exporting would be a problem.
149
150 You also don't need to use C<warnings> and C<strict>, since the
151 definition of a library automatically exports those.
152
153 =head1 LIBRARY USAGE
154
155 You can import the L<"type helpers"|/"TYPE HANDLER FUNCTIONS"> of a
156 library by C<use>ing it with a list of types to import as arguments. If
157 you want all of them, use the C<:all> tag. For example:
158
159   use MyLibrary      ':all';
160   use MyOtherLibrary qw( TypeA TypeB );
161
162 MooseX::Types comes with a library of Moose' built-in types called
163 L<MooseX::Types::Moose>.
164
165 =head1 WRAPPING A LIBRARY
166
167 You can define your own wrapper subclasses to manipulate the behaviour
168 of a set of library exports. Here is an example:
169
170   package MyWrapper;
171   use strict;
172   use Class::C3;
173   use base 'MooseX::Types::Wrapper';
174
175   sub coercion_export_generator {
176       my $class = shift;
177       my $code = $class->next::method(@_);
178       return sub {
179           my $value = $code->(@_);
180           warn "Coercion returned undef!"
181               unless defined $value;
182           return $value;
183       };
184   }
185
186   1;
187
188 This class wraps the coercion generator (e.g., C<to_Int()>) and warns
189 if a coercion returned an undefined value. You can wrap any library
190 with this:
191
192   package Foo;
193   use strict;
194   use MyWrapper MyLibrary => [qw( Foo Bar )],
195                 Moose     => [qw( Str Int )];
196
197   ...
198   1;
199
200 The C<Moose> library name is a special shortcut for 
201 L<MooseX::Types::Moose>.
202
203 =head2 Generator methods you can overload
204
205 =over 4
206
207 =item type_export_generator( $short, $full )
208
209 Creates a closure returning the type's L<Moose::Meta::TypeConstraint> 
210 object. 
211
212 =item check_export_generator( $short, $full, $undef_message )
213
214 This creates the closure used to test if a value is valid for this type.
215
216 =item coercion_export_generator( $short, $full, $undef_message )
217
218 This is the closure that's doing coercions.
219
220 =back
221
222 =head2 Provided Parameters
223
224 =over 4
225
226 =item $short
227
228 The short, exported name of the type.
229
230 =item $full
231
232 The fully qualified name of this type as L<Moose> knows it.
233
234 =item $undef_message
235
236 A message that will be thrown when type functionality is used but the
237 type does not yet exist.
238
239 =back
240
241 =head1 METHODS
242
243 =head2 import
244
245 Installs the L<MooseX::Types::Base> class into the caller and 
246 exports types according to the specification described in 
247 L</"LIBRARY DEFINITION">. This will continue to 
248 L<Moose::Util::TypeConstraints>' C<import> method to export helper
249 functions you will need to declare your types.
250
251 =cut
252
253 sub import {
254     my ($class, %args) = @_;
255     my  $callee = caller;
256
257     # everyone should want this
258     strict->import;
259     warnings->import;
260
261     # inject base class into new library
262     {   no strict 'refs';
263         unshift @{ $callee . '::ISA' }, 'MooseX::Types::Base';
264     }
265
266     # generate predeclared type helpers
267     if (my @orig_declare = @{ $args{ -declare } || [] }) {
268         my ($tags, $declare) = filter_tags @orig_declare;
269
270         for my $type (@$declare) {
271
272             croak "Cannot create a type containing '::' ($type) at the moment"
273                 if $type =~ /::/;
274
275             $callee->add_type($type);
276             $callee->export_type_into(
277                 $callee, $type, 
278                 sprintf($UndefMsg, $type, $callee), 
279                 -full => 1,
280             );
281         }
282     }
283
284     # run type constraints import
285     return Moose::Util::TypeConstraints->import({ into => $callee });
286 }
287
288 =head2 type_export_generator
289
290 Generate a type export, e.g. C<Int()>. This will return either a
291 L<Moose::Meta::TypeConstraint> object, or alternatively a
292 L<MooseX::Types::UndefinedType> object if the type was not
293 yet defined.
294
295 =cut
296
297 sub type_export_generator {
298     my ($class, $type, $full) = @_;
299     return sub { 
300         return find_type_constraint($full)
301             || MooseX::Types::UndefinedType->new($full);
302     };
303 }
304
305 =head2 coercion_export_generator
306
307 This generates a coercion handler function, e.g. C<to_Int($value)>. 
308
309 =cut
310
311 sub coercion_export_generator {
312     my ($class, $type, $full, $undef_msg) = @_;
313     return sub {
314         my ($value) = @_;
315
316         # we need a type object
317         my $tobj = find_type_constraint($full) or croak $undef_msg;
318         my $return = $tobj->coerce($value);
319
320         # non-successful coercion returns false
321         return unless $tobj->check($return);
322
323         return $return;
324     }
325 }
326
327 =head2 check_export_generator
328
329 Generates a constraint check closure, e.g. C<is_Int($value)>.
330
331 =cut
332
333 sub check_export_generator {
334     my ($class, $type, $full, $undef_msg) = @_;
335     return sub {
336         my ($value) = @_;
337
338         # we need a type object
339         my $tobj = find_type_constraint($full) or croak $undef_msg;
340
341         return $tobj->check($value);
342     }
343 }
344
345 =head1 CAVEATS
346
347 A library makes the types quasi-unique by prefixing their names with (by
348 default) the library package name. If you're only using the type handler
349 functions provided by MooseX::Types, you shouldn't ever have to use
350 a type's actual full name.
351
352 =head1 SEE ALSO
353
354 L<Moose>, L<Moose::Util::TypeConstraints>, L<MooseX::Types::Moose>
355
356 =head1 AUTHOR AND COPYRIGHT
357
358 Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
359 the C<#moose> cabal on C<irc.perl.org>.
360
361 =head1 LICENSE
362
363 This program is free software; you can redistribute it and/or modify
364 it under the same terms as perl itself.
365
366 =cut
367
368 1;