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