File Coverage

blib/lib/Metabase/Resource.pm
Criterion Covered Total %
statement 62 65 95.3
branch 15 20 75.0
condition 9 18 50.0
subroutine 16 19 84.2
pod 5 5 100.0
total 107 127 84.2


line stmt bran cond sub pod time code
1 10     10   2554 use 5.006;
  10         24  
2 10     10   34 use strict;
  10         12  
  10         184  
3 10     10   30 use warnings;
  10         21  
  10         419  
4              
5             package Metabase::Resource;
6              
7             our $VERSION = '0.025';
8              
9 10     10   29 use Carp ();
  10         12  
  10         708  
10              
11             #--------------------------------------------------------------------------#
12             # main API methods -- shouldn't be overridden
13             #--------------------------------------------------------------------------#
14              
15             use overload (
16 91     91   6298 '""' => sub { $_[0]->resource },
17 0     0   0 '==' => sub { _obj_eq(@_) },
18 0     0   0 '!=' => sub { !_obj_eq(@_) },
19 10         103 fallback => 1,
20 10     10   38 );
  10         14  
21              
22             # Check if two objects are the same object
23             sub _obj_eq {
24 0     0   0 return overload::StrVal( $_[0] ) eq overload::StrVal( $_[1] );
25             }
26              
27             my $id_re = qr/[_a-z]+/i;
28             my $class_re = qr/^$id_re(?:::$id_re)*$/;
29              
30             sub _load {
31 125     125   113 my ( $class, $subclass ) = @_;
32 125 100       615 unless ( $subclass =~ $class_re ) {
33 1         83 Carp::confess "'$subclass' does not look like a class name";
34             }
35 124 50       5456 eval "require $subclass; 1" ## no critic
36             or Carp::confess("Could not load '$subclass': $@");
37             }
38              
39             my %installed;
40              
41             sub _add {
42 226     226   209 my ( $self, $name, $value ) = @_;
43 226         957 $self->{metadata}{$name} = $value;
44 226         270 my $method = ref($self) . "::$name";
45 226 100       314 if ( !$installed{$method} ) {
46 10     10   2488 no strict 'refs'; ## no critic
  10         13  
  10         3929  
47 42     48   101 *{$method} = sub { return $_[0]->{metadata}{$name} };
  42         144  
  48         512  
48 42         74 $installed{$method}++;
49             }
50 226         306 return;
51             }
52              
53             sub _type {
54 62     62   61 my ($self) = @_;
55 62   33     105 my $class = ref $self || $self;
56 62         181 $class =~ s{::}{-}g;
57 62         102 return $class;
58             }
59              
60             sub new {
61 66     66 1 2806 my ( $class, $resource ) = @_;
62 66 100 66     973 Carp::confess("no resource string provided")
63             unless defined $resource && length $resource;
64              
65 63 100 66     124 if ( ref $resource && eval { $resource->isa('Metabase::Resource') } ) {
  1         5  
66 1         2 $resource = $resource->resource;
67             }
68              
69             # parse scheme
70 63         225 my ($scheme) = $resource =~ m{\A([^:]+):};
71 63 100 66     387 Carp::confess("could not determine URI scheme from '$resource'\n")
72             unless defined $scheme && length $scheme;
73              
74 62         85 my $schema_class = "Metabase::Resource::$scheme";
75 62         98 $class->_load($schema_class);
76 62         209 my $type_class = $schema_class->_extract_type($resource);
77 62         118 $class->_load($type_class);
78              
79             # construct object
80 62         225 my $self = bless {
81             resource => $resource,
82             metadata => {},
83             }, $type_class;
84 62 50       267 if ( $self->can('_init') ) {
85 62         148 $self->_init;
86             }
87              
88 62         400 $self->_add( type => $self->_type );
89 62         119 $self->validate;
90 62         116 return $self;
91             }
92              
93             # Don't cause segfault with perl-5.6.1 by
94             # overloading undef stuff...
95             sub resource {
96 128 50 33 128 1 2218 return '' unless ref $_[0] && defined $_[0]->{resource};
97 128         507 return "$_[0]->{resource}";
98             }
99              
100             # return a copy
101             sub metadata {
102 3     3 1 8 my ($self) = @_;
103 3 50       4 return { %{ $self->{metadata} || {} } };
  3         22  
104             }
105              
106             sub metadata_types {
107 3     3 1 6 my ($self) = @_;
108             return {
109             'type' => '//str',
110 3 50       3 %{ $self->_metadata_types || {} }
  3         11  
111             };
112             }
113              
114             #--------------------------------------------------------------------------#
115             # abstract methods -- fatal
116             #--------------------------------------------------------------------------#
117              
118             sub validate {
119 1     1 1 412 my ($self) = @_;
120 1   33     86 Carp::confess "validate not implemented by " . ( ref $self || $self );
121             }
122              
123             1;
124              
125             # ABSTRACT: factory class for Metabase resource descriptors
126              
127             __END__