File Coverage

blib/lib/Atomik/MediaType.pm
Criterion Covered Total %
statement 12 27 44.4
branch 0 6 0.0
condition n/a
subroutine 4 6 66.6
pod n/a
total 16 39 41.0


line stmt bran cond sub pod time code
1             # $Id: /mirror/coderepos/lang/perl/Atomik/trunk/lib/Atomik/MediaType.pm 67588 2008-07-31T05:00:38.496278Z daisuke $
2              
3             package Atomik::MediaType;
4 1     1   8 use Moose;
  1         3  
  1         10  
5 1     1   7242 use Moose::Util::TypeConstraints qw(coerce from via);
  1         4  
  1         10  
6              
7             use overload
8 1         11 '""' => \&as_string,
9             fallback => 1
10 1     1   594 ;
  1         2  
11              
12             coerce 'Atomik::MediaType'
13             => from 'Str'
14             => via {
15             Atom::MediaType->from_string( $_ );
16             }
17             ;
18              
19             has 'type' => (
20             is => 'rw',
21             isa => 'Str',
22             required => 1,
23             );
24              
25             has 'subtype_major' => (
26             is => 'rw',
27             isa => 'Str',
28             );
29              
30             has 'subtype_minor' => (
31             is => 'rw',
32             isa => 'Maybe[Str]',
33             );
34              
35             has 'parameters' => (
36             is => 'rw',
37             isa => 'Maybe[Str]'
38             );
39              
40             __PACKAGE__->meta->make_immutable;
41              
42 1     1   200 no Moose;
  1         3  
  1         5  
43              
44             sub BUILDARGS {
45 0     0     my ($class, %args) = @_;
46              
47 0 0         if (my $subtype = delete $args{subtype}) {
48 0           my ($subtype_major, $subtype_minor);
49 0 0         if ($subtype =~ /^([^\+]+)\+(.+)$/) {
50 0           $subtype_major = $1;
51 0           $subtype_minor = $2;
52             } else {
53 0           $subtype_major = $subtype;
54             }
55              
56 0           $args{subtype_major} = $subtype_major;
57 0           $args{subtype_minor} = $subtype_minor;
58             }
59              
60 0           return { %args };
61             }
62              
63             sub subtype {
64 0     0     my $self = shift;
65 0           my @subtype = ( $self->subtype_major );
66 0 0         if (my $minor = $self->subtype_minor) {
67 0           push @subtype, $minor;
68             }
69 0           return join('+', @subtype);
70             }
71              
72             # XXX - bad naming.
73             sub assert_subtype_of {
74             my ($self, $other) = @_;
75              
76             if (! blessed $other) {
77             $other = Atomik::MediaType->from_string($other);
78             }
79              
80             if (! $self->is_subtype($other)) {
81             confess "$other is not a subtype of $self";
82             }
83             }
84              
85             sub from_string {
86             my ($class, $string) = @_;
87             if ($string !~ /^([^\/]+)\/([^;]+)\s*(?:;\s*(.*))?$/) {
88             confess "Could not parse '$string' as a media type";
89             }
90             my ($type, $subtype, $parameters) = ($1, $2, $3);
91              
92             my $obj = $class->new(
93             type => $type,
94             subtype => $subtype,
95             parameters => $parameters,
96             );
97             return $obj;
98             }
99              
100             sub as_string {
101             my $self = shift;
102              
103             my @components = ($self->type);
104             if (my $subtype = $self->subtype) {
105             push @components, $subtype;
106             }
107              
108             if (my $parameters = $self->parameters) {
109             push @components, $parameters;
110             }
111              
112             if (@components == 3) {
113             return sprintf('%s/%s;%s', @components);
114             } elsif (@components == 2) {
115             return sprintf('%s/%s', @components);
116             } else {
117             return $components[0];
118             }
119             }
120              
121             sub is_subtype {
122             my ($self, $other) = @_;
123              
124             # wild card against something is always true
125             if ( $self->type eq '*' ) {
126             return 1;
127             }
128              
129             # if the main types do not match, then this is false
130             if ( $self->type ne $other->type ) {
131             return 0;
132             }
133              
134             if ( $self->subtype eq '*' ) {
135             return 1;
136             }
137              
138             if (! $other->subtype_minor) {
139             if ($self->subtype_major ne $other->subtype_major) {
140             return 0;
141             }
142             } elsif ( $self->subtype ne $other->subtype ) {
143             return 0;
144             }
145              
146             # if parameters exist, they must be compared iff BOTH medias
147             # have a parameter list
148             if ( ! $self->parameters || ! $other->parameters) {
149             return 1;
150             }
151              
152             return $self->parameters eq $other->parameters;
153             }
154              
155             # pre-defined types.
156             # this is placed last so that we can safely use class methods at BEGIN time
157             our $INITIALIZED;
158             if (! $INITIALIZED) {
159             my %TYPES = (
160             entry => 'application/atom+xml;type=entry',
161             feed => 'application/atom+xml;type=feed',
162             service => 'application/atomsvc+xml',
163             category => 'application/atomcat+xml',
164             );
165             require constant;
166             while ( my ($name, $type) = each %TYPES ) {
167             my $obj = __PACKAGE__->from_string($type) ;
168             constant->import( uc $name => $obj );
169             }
170             $INITIALIZED = 1;
171             }
172             use Sub::Exporter -setup => {
173             exports => [ qw(ENTRY FEED SERVICE CATEGORY) ]
174             };
175              
176             1;