Add support for :all on MooseX::Types::Combine
[gitmo/MooseX-Types.git] / lib / MooseX / Types / Combine.pm
1 package MooseX::Types::Combine;
2
3 # ABSTRACT: Combine type libraries for exporting
4
5 use strict;
6 use warnings;
7 use Class::MOP ();
8
9 =head1 SYNOPSIS
10
11     package CombinedTypeLib;
12
13     use base 'MooseX::Types::Combine';
14
15     __PACKAGE__->provide_types_from(qw/TypeLib1 TypeLib2/);
16
17     package UserClass;
18
19     use CombinedTypeLib qw/Type1 Type2 ... /;
20
21 =head1 DESCRIPTION
22
23 Allows you to export types from multiple type libraries. 
24
25 Libraries on the right side of the type libs passed to L</provide_types_from>
26 take precedence over those on the left in case of conflicts.
27
28 =cut
29
30 sub import {
31     my ($class, @types) = @_;
32     my $caller = caller;
33
34     my %types = $class->_provided_types;
35
36     if ( grep { $_ eq ':all' } @types ){
37       $_->import({ -into => $caller }, q{:all} ) for $class->provide_types_from;
38       return;
39     }
40
41     my %from;
42     for my $type (@types) {
43         unless ($types{$type}) {
44             my @type_libs = $class->provide_types_from;
45
46             die
47                 "$caller asked for a type ($type) which is not found in any of the"
48                 . " type libraries (@type_libs) combined by $class\n";
49         }
50
51         push @{ $from{ $types{$type} } }, $type;
52     }
53
54     $_->import({ -into => $caller }, @{ $from{ $_ } })
55         for keys %from;
56 }
57
58 =head1 CLASS METHODS
59
60 =head2 provide_types_from
61
62 Sets or returns a list of type libraries to re-export from.
63
64 =cut
65
66 sub provide_types_from {
67     my ($class, @libs) = @_;
68
69     my $store =
70      do { no strict 'refs'; \@{ "${class}::__MOOSEX_TYPELIBRARY_LIBRARIES" } };
71
72     if (@libs) {
73         $class->_check_type_lib($_) for @libs;
74         @$store = @libs;
75
76         my %types = map {
77             my $lib = $_;
78             map +( $_ => $lib ), $lib->type_names
79         } @libs;
80
81         $class->_provided_types(%types);
82     }
83
84     @$store;
85 }
86
87 sub _check_type_lib {
88     my ($class, $lib) = @_;
89
90     Class::MOP::load_class($lib);
91
92     die "Cannot use $lib in a combined type library, it does not provide any types"
93         unless $lib->can('type_names');
94 }
95
96 sub _provided_types {
97     my ($class, %types) = @_;
98
99     my $types =
100      do { no strict 'refs'; \%{ "${class}::__MOOSEX_TYPELIBRARY_TYPES" } };
101
102     %$types = %types
103         if keys %types;
104
105     %$types;
106 }
107
108 =head1 SEE ALSO
109
110 L<MooseX::Types>
111
112 =head1 LICENSE
113
114 This program is free software; you can redistribute it and/or modify
115 it under the same terms as perl itself.
116
117 =cut
118
119 1;