73e1e2037fa41a67e5f35ed1c63f7cb449b6ddea
[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     my %from;
37     for my $type (@types) {
38         unless ($types{$type}) {
39             my @type_libs = $class->provide_types_from;
40
41             die
42                 "$caller asked for a type ($type) which is not found in any of the"
43                 . " type libraries (@type_libs) combined by $class\n";
44         }
45
46         push @{ $from{ $types{$type} } }, $type;
47     }
48
49     $_->import({ -into => $caller }, @{ $from{ $_ } })
50         for keys %from;
51 }
52
53 =head1 CLASS METHODS
54
55 =head2 provide_types_from
56
57 Sets or returns a list of type libraries to re-export from.
58
59 =cut
60
61 sub provide_types_from {
62     my ($class, @libs) = @_;
63
64     my $store =
65      do { no strict 'refs'; \@{ "${class}::__MOOSEX_TYPELIBRARY_LIBRARIES" } };
66
67     if (@libs) {
68         $class->_check_type_lib($_) for @libs;
69         @$store = @libs;
70
71         my %types = map {
72             my $lib = $_;
73             map +( $_ => $lib ), $lib->type_names
74         } @libs;
75
76         $class->_provided_types(%types);
77     }
78
79     @$store;
80 }
81
82 sub _check_type_lib {
83     my ($class, $lib) = @_;
84
85     Class::MOP::load_class($lib);
86
87     die "Cannot use $lib in a combined type library, it does not provide any types"
88         unless $lib->can('type_names');
89 }
90
91 sub _provided_types {
92     my ($class, %types) = @_;
93
94     my $types =
95      do { no strict 'refs'; \%{ "${class}::__MOOSEX_TYPELIBRARY_TYPES" } };
96
97     %$types = %types
98         if keys %types;
99
100     %$types;
101 }
102
103 =head1 SEE ALSO
104
105 L<MooseX::Types>
106
107 =head1 LICENSE
108
109 This program is free software; you can redistribute it and/or modify
110 it under the same terms as perl itself.
111
112 =cut
113
114 1;