File Coverage

blib/lib/Metabase/Resource.pm
Criterion Covered Total %
statement 63 66 95.4
branch 15 20 75.0
condition 9 18 50.0
subroutine 16 19 84.2
pod 5 5 100.0
total 108 128 84.3


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