File Coverage

blib/lib/Class/PObject.pm
Criterion Covered Total %
statement 64 77 83.1
branch 15 26 57.6
condition 6 10 60.0
subroutine 8 8 100.0
pod 0 1 0.0
total 93 122 76.2


line stmt bran cond sub pod time code
1             package Class::PObject;
2              
3             # PObject.pm,v 1.57 2005/02/20 18:05:00 sherzodr Exp
4              
5 3     3   20 use strict;
  3         5  
  3         98  
6             #use diagnostics;
7 3     3   7464 use Log::Agent;
  3         22505  
  3         290  
8 3     3   17 use vars ('$VERSION', '$revision');
  3         7  
  3         274  
9              
10             $VERSION = '2.17';
11             $revision = '1.57';
12              
13             # configuring Log::Agent
14             logconfig(-level=>$ENV{POBJECT_DEBUG} || 0);
15              
16             sub import {
17 7     7   13 my $class = shift;
18 7         23 my $caller_pkg = (caller)[0];
19              
20 7 50       24 unless ( @_ ) {
21 3     3   13 no strict 'refs';
  3         6  
  3         520  
22 7         8 *{ "$caller_pkg\::pobject" } = \&{ "$class\::pobject" };
  7         41  
  7         26  
23 7         107 return 1
24             }
25 0         0 require Exporter;
26 0         0 return $class->Exporter::import( @_ )
27             }
28              
29             sub pobject {
30 5     5 0 11 my ($class, $props);
31              
32             # are we given explicit class name to be created in?
33 5 50 0     22 if ( @_ == 2 ) {
    0          
34 5         14 ($class, $props) = @_;
35 5         184 logtrc 1, "pobject %s => %s", $class, $props
36             }
37             # Is class name assumed to be the current caller's package?
38             elsif ( $_[0] && (ref($_[0]) eq 'HASH') ) {
39 0         0 $props = $_[0];
40 0         0 $class = (caller())[0];
41 0         0 logtrc 1, "pobject ('%s'), %s", $class, $props
42             }
43             # otherwise, we throw a usage exception:
44             else {
45 0         0 logcroak "Usage error"
46             }
47             # should we make sure that current package is not 'main'?
48 5 50       522 if ( $class eq 'main' ) {
49 0         0 logcroak "'main' cannot be the class name"
50             }
51              
52             # creating the class virtually. Note, that it is different
53             # then the way Class::Struct works. Class::Struct literally builds
54             # the class contents in a string, and then eval()s them.
55             # And we play with symtables. However, I'm not sure how secure this method is.
56              
57 3     3   14 no strict 'refs';
  3         4  
  3         1404  
58             # if the properties have already been created, it means the user
59             # is declaring the class with the same name twice. He should be shot!
60 5 50       10 if ( ${ "$class\::props" } ) {
  5         61  
61 0         0 logcroak "are you trying to create the same class two times?"
62             }
63              
64             # we should have some columns
65 5 50       9 unless ( @{$props->{columns}} ) {
  5         24  
66 0         0 logcroak "class '%s' should have columns!", $class
67             }
68              
69             # one of the columns should be 'id'. I believe this is a limitation,
70             # which should be eliminated in next release
71 5         10 my $has_id = 0;
72 5         10 for ( @{$props->{columns}} ) {
  5         16  
73 5 50       22 $has_id = ($_ eq 'id') and last
74             }
75 5 50       15 unless ( $has_id ) {
76 0         0 logcroak "one of the columns must be 'id'"
77             }
78              
79             # certain method names are reserved. Making sure they won't get overridden
80 5         28 my @reserved_methods = qw(
81             new load fetch save remove remove_all set get
82             pobject_init set_datasource set_driver drop_datasource DESTROY
83             );
84 5         12 for my $method ( @reserved_methods ) {
85 65         88 for my $column ( @{$props->{columns}} ) {
  65         114  
86 247 50       494 if ( $method eq $column ) {
87 0         0 logcroak "method '%s' is reserved", $method
88             }
89             }
90             }
91              
92 5         11 for my $colname ( @{$props->{columns}} ) {
  5         15  
93 19 100 100     108 unless ( defined($props->{tmap}) && $props->{tmap}->{$colname} ) {
94 12 100       29 if ( $colname eq 'id' ) {
95 4         15 $props->{tmap}->{$colname} = 'INTEGER', next
96             }
97 8         73 $props->{tmap}->{$colname} = 'VARCHAR(255)'
98             }
99             }
100              
101             # if no driver was specified, default driver to be used is 'file'
102 5   100     24 $props->{driver} ||= 'file';
103              
104             # if no serializer set defaulting to 'storable'
105 5   50     42 $props->{serializer} ||= 'storable';
106              
107             # it's important that we cache all the properties passed to the pobject()
108             # as a static data. This lets multiple instances of the pobject to access
109             # this data whenever needed
110 5         10 ${ "$class\::props" } = $props;
  5         20  
111              
112 5         2141 require Class::PObject::Template;
113             # To ensure operator overloading works properly on these
114             # objects, let's also set the caller's @ISA array:
115 5         15 push @{ "$class\::ISA" }, "Class::PObject::Template";
  5         76  
116              
117             # creating accessor methods
118 5         15 for my $colname ( @{ $props->{columns} } ) {
  5         18  
119 19 50       188 if ( $class->UNIVERSAL::can($colname) ) {
120 0         0 logcarp "method '%s' exists in the caller's package", $colname;
121             next
122 0         0 }
123 19         93 *{ "$class\::$colname" } = sub {
124 201 100   201   580 if ( @_ == 2 ) {
125 37         81 my $set = \&Class::PObject::Template::set;
126 37         154 return $set->( $_[0], $colname, $_[1] )
127             }
128 164         289 my $get = \&Class::PObject::Template::get;
129 164         514 return $get->( $_[0], $colname )
130             }
131 19         76 }
132             }
133              
134             logtrc 1, "%s loaded successfully", __PACKAGE__;
135              
136             1;
137             __END__