File Coverage

blib/lib/Data/Object/Prototype.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             # ABSTRACT: Data::Object Prototype-based Programming
2             package Data::Object::Prototype;
3              
4 1     1   544 use 5.10.0;
  1         2  
  1         39  
5              
6 1     1   3 use strict;
  1         1  
  1         25  
7 1     1   9 use warnings;
  1         2  
  1         28  
8              
9 1     1   3 use Carp ();
  1         1  
  1         12  
10              
11 1     1   436 use Data::Object::Class;
  1         11925  
  1         8  
12 1     1   1301 use Data::Object::Signatures;
  0            
  0            
13              
14             use Data::Object::Prototype::Attribute;
15             use Data::Object::Prototype::Method;
16              
17             use Data::Object::Library -types;
18              
19             our $VERSION = '0.03'; # VERSION
20              
21             has 'package' => (
22             is => 'ro',
23             isa => Str,
24             default => fun { join '::', ref shift, '__ANON__' },
25             lazy => 1,
26             );
27              
28             has 'series' => (
29             is => 'ro',
30             isa => Str,
31             default => fun { join '::', shift->package, 'Instance' },
32             lazy => 1,
33             );
34              
35             has 'inherits' => (
36             is => 'ro',
37             isa => ArrayObj[Str],
38             default => fun { [] },
39             coerce => 1,
40             lazy => 1,
41             );
42              
43             has 'includes' => (
44             is => 'ro',
45             isa => ArrayObj[Str],
46             default => fun { [] },
47             coerce => 1,
48             lazy => 1,
49             );
50              
51             has 'attributes' => (
52             is => 'ro',
53             isa => ArrayObj[InstanceOf['Data::Object::Prototype::Attribute']],
54             default => fun { [] },
55             coerce => 1,
56             lazy => 1,
57             );
58              
59             has 'methods' => (
60             is => 'ro',
61             isa => ArrayObj[InstanceOf['Data::Object::Prototype::Method']],
62             default => fun { [] },
63             coerce => 1,
64             lazy => 1,
65             );
66              
67             fun BUILDARGS ($class, %args) {
68             my @properties = grep qr/^[\&\$]/, sort keys %args;
69              
70             for my $key (@properties) {
71             if (my ($name) = $key =~ /\$(\w+)/) {
72             push @{$args{attributes}} =>
73             Data::Object::Prototype::Attribute->new(
74             name => $name,
75             options => $args{$key},
76              
77             );
78             }
79             if (my ($name) = $key =~ /\&(\w+)/) {
80             push @{$args{methods}} =>
81             Data::Object::Prototype::Method->new(
82             name => $name,
83             routine => $args{$key},
84             );
85              
86             }
87             }
88              
89             return \%args;
90             }
91              
92             my %counter;
93             method class () {
94             my $series = $self->series;
95             my $format = join '::', $series, '%04d';
96             my $instance = sprintf $format, ++$counter{$series};
97             my @statement = "package $instance";
98             my @supers = 'Data::Object::Prototype::Instance';
99             my $default = 'Data::Object::Class';
100              
101             if (my $inherits = $self->inherits) {
102             push @supers, $inherits->list;
103             }
104              
105             push @statement, "use $default",
106             map "extends '$_'", @supers, ();
107              
108             unless ($counter{$instance}++) {
109             local $@; eval join '; ', @statement; Carp::croak $@ if $@;
110             }
111              
112             my $package = $instance->package;
113              
114             $package->method(prototype => sub { $self });
115              
116             my $methods = $self->methods;
117             for my $method ($methods->list) {
118             my $name = $method->name;
119             my $data = $method->routine->data;
120             $package->method($name, $data);
121             }
122              
123             my $includes = $self->includes;
124             for my $include ($includes->list) {
125             $package->mixin_role($include);
126             }
127              
128             my $attributes = $self->attributes;
129             for my $attribute ($attributes->list) {
130             my $name = $attribute->name;
131             my $data = $attribute->options;
132             $package->attribute($name, @$data);
133             }
134              
135             return $instance;
136             }
137              
138             method create ($class: %args) {
139             return $class->new(%args)->class;
140             }
141              
142             method extend (%args) {
143             $args{package} //= $self->package,
144             $args{series} //= $self->series,
145             $args{inherits} //= $self->inherits,
146             $args{includes} //= $self->includes,
147             $args{attributes} //= $self->attributes,
148             $args{methods} //= $self->methods,
149              
150             return ref($self)->new(%args)->class;
151             }
152              
153             1;
154              
155             __END__