/[cvs]/nfo/perl/libs/Data/Mungle/Code/Ref.pm
ViewVC logotype

Contents of /nfo/perl/libs/Data/Mungle/Code/Ref.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (show annotations)
Thu Mar 27 15:31:03 2003 UTC (21 years, 3 months ago) by joko
Branch: MAIN
Changes since 1.4: +5 -2 lines
fixes to modules regarding new namespace(s) below Data::Mungle::*

1 ## ---------------------------------------------------------------------------
2 ## $Id: Ref.pm,v 1.4 2003/03/27 15:17:03 joko Exp $
3 ## ---------------------------------------------------------------------------
4 ## $Log: Ref.pm,v $
5 ## Revision 1.4 2003/03/27 15:17:03 joko
6 ## namespace fixes for Data::Mungle::*
7 ##
8 ## Revision 1.3 2003/02/20 19:33:28 joko
9 ## refactored code from Data.Transform.Deep
10 ## + sub ref_slot
11 ## + sub expr2perl
12 ##
13 ## Revision 1.2 2003/02/20 18:55:46 joko
14 ## + minor cosmetic update
15 ##
16 ## Revision 1.1 2003/01/22 17:59:22 root
17 ## + refactored from Mail::Audit::Dispatch
18 ##
19 ## ---------------------------------------------------------------------------
20
21
22 package Data::Mungle::Code::Ref;
23
24 use strict;
25 use warnings;
26
27 require Exporter;
28 our @ISA = qw( Exporter );
29 our @EXPORT_OK = qw(
30 &get_coderef
31 &ref_slot
32 );
33
34
35 sub get_coderef {
36 my $codepack = shift;
37 my $method = shift;
38 $codepack || return '[error]';
39 $method ||= '';
40 $method && ($codepack .= '::');
41 return eval '\&' . $codepack . $method . ';';
42 }
43
44
45 # this function seems to do similar stuff like these below (refexpr2perlref & co.)
46 # TODO: maybe this mechanism can be replaced completely through some nice module from CPAN .... ? ;-)
47 sub _ref_slot_bylist {
48 my $var = shift;
49 my $indexstack_ref = shift;
50 my @indexstack = @{$indexstack_ref};
51 my $joiner = '->';
52 my @evlist;
53 foreach (@indexstack) {
54 my $elem;
55 if ($_ =~ m/\d+/) { $elem = "[$_]"; }
56 if ($_ =~ m/\D+/) { $elem = "{$_}"; }
57 push @evlist, $elem;
58 }
59 my $evstring = join($joiner, @evlist);
60 $evstring = 'return $var->' . $evstring . ';';
61 #print "ev: $evstring\n";
62 return eval($evstring);
63 }
64
65
66 sub ref_slot {
67
68 my $obj = shift;
69 my $expr = shift;
70 my $values = shift;
71 my $delimiter = shift;
72
73 $delimiter ||= '->';
74
75 my $value;
76 # detect for callback (code-reference)
77 if (ref($expr) eq 'CODE') {
78 $value = &$expr($obj);
79
80 } elsif (ref($expr) eq 'ARRAY') {
81 return _ref_slot_bylist($obj, $expr);
82
83 } elsif ($expr =~ m/$delimiter/) {
84 # use expr as complex object reference declaration (obj->subObj->subSubObj->0->attribute)
85 (my $objPerlRefString, my $parts) = expr2perl($expr, $delimiter);
86
87 # trace
88 #print "expr: $expr", "\n";
89 #print "objPerlRefString: $objPerlRefString", "\n";
90
91 my $evstr = '$obj' . '->' . $objPerlRefString;
92
93 # trace
94 #print "eval: $evstr", "\n";
95
96 $value = eval($evstr);
97 die ($@) if $@;
98
99 # if value isn't set, try to set it
100 my $callbackMap;
101 if ($values) {
102 #if (ref $values eq 'HASH') {
103 if (ref $values eq 'Data::Map') {
104 $callbackMap = $values->getAttributes();
105 } else {
106 # apply $values as single value to referenced slot
107 #print "APPLY!", "\n";
108 eval('$obj' . '->' . $objPerlRefString . ' = $values;');
109 die ($@) if $@;
110 }
111 }
112
113 # determine $values - if it's a hashref, use it as a "valueMap"
114 # "fallback" to callbackMap
115 # callbacks are applied this way:
116 # take the last element of the expression parts and check if this string exists as a key in the callback-map
117 if (!$value && $callbackMap) {
118 #print Dumper($callbackMap);
119
120 # prepare needle
121 my @parts = @$parts;
122 my $count = $#parts;
123 my $needle = $parts[$count];
124
125 # prepare haystack
126 my @haystack = keys %$callbackMap;
127 if (grep($needle, @haystack)) {
128 $value = $callbackMap->{$needle}->();
129 #print "value: ", $value, "\n";
130 }
131 }
132
133 } else {
134 # use expr as simple scalar key (attributename)
135 $value = $obj->{$expr};
136 }
137
138 return $value;
139
140 }
141
142
143 sub expr2perl {
144 my $expr = shift;
145 my $delimiter = shift;
146
147 $delimiter = quotemeta($delimiter);
148
149 # split expression by dereference operators first
150 my @parts_pure = split(/$delimiter/, $expr);
151
152 # wrap []'s around each part, if it consists of numeric characters only (=> numeric = array-index),
153 # use {}'s, if there are word-characters in it (=> alphanumeric = hash-key)
154 my @parts_capsule = @parts_pure;
155 map {
156 m/^\d+$/ && ($_ = "[$_]") || ($_ = "{$_}");
157 } @parts_capsule;
158
159 # join parts with dereference operators together again and return built string
160 return (join('->', @parts_capsule), \@parts_pure);
161 }
162
163
164 1;
165 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed