/[cvs]/nfo/perl/libs/Data/Transfer/Sync/Metadata.pm
ViewVC logotype

Contents of /nfo/perl/libs/Data/Transfer/Sync/Metadata.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (show annotations)
Fri Feb 14 14:06:20 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
Changes since 1.3: +5 -2 lines
+ minor fix to old metadata structure

1 ## $Id: Metadata.pm,v 1.3 2003/02/11 06:28:24 joko Exp $
2 ##
3 ## Copyright (c) 2002 Andreas Motl <andreas.motl@ilo.de>
4 ##
5 ## See COPYRIGHT section in pod text below for usage and distribution rights.
6 ##
7 ## ----------------------------------------------------------------------------------------
8 ## $Log: Metadata.pm,v $
9 ## Revision 1.3 2003/02/11 06:28:24 joko
10 ## + changes to metadata structure
11 ##
12 ## Revision 1.2 2003/02/09 05:02:05 joko
13 ## + major structure changes
14 ## - refactored code to sister modules
15 ##
16 ## Revision 1.1 2003/01/20 16:58:46 joko
17 ## + initial check-in: here they are....
18 ##
19 ## Revision 1.1 2003/01/19 01:23:04 joko
20 ## + new from Data/Transfer/Sync.pm
21 ##
22 ## ----------------------------------------------------------------------------------------
23
24
25 package Data::Transfer::Sync::Metadata;
26
27 use strict;
28 use warnings;
29
30 use mixin::with qw( Data::Transfer::Sync );
31
32
33 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - main
34
35 use Data::Dumper;
36 use libdb qw( quotesql );
37 use Data::Transform::Deep qw( refexpr2perlref );
38
39 # get logger instance
40 my $logger = Log::Dispatch::Config->instance;
41
42 # TODO: refactor (still)!!! take this list from already established/given metadata ....
43 # .... also internally: passing around and mungling these metadata doesn't make sense anymore.
44 sub options2metadata {
45 my $self = shift;
46
47 $logger->debug( __PACKAGE__ . "->transformMetadata" );
48
49 # trace
50 #print Dumper($self->{options});
51 #print Dumper($self->{args_raw});
52 #exit;
53
54 # decompose identifiers and write to metadata (for each descent)
55 foreach ('source', 'target') {
56
57 # get/set metadata for further processing
58
59 $self->{options}->{$_}->{dbKey} ||= '';
60 $self->{options}->{$_}->{nodeType} ||= '';
61 $self->{options}->{$_}->{nodeName} ||= '';
62
63 # Partner and Node (compare the V1-notations: "L:Country" or "R:countries.csv")
64 $self->{meta}->{$_}->{dbKey} = $self->{options}->{$_}->{dbKey};
65 $self->{meta}->{$_}->{nodeType} = $self->{options}->{$_}->{nodeType};
66 $self->{meta}->{$_}->{nodeName} = $self->{options}->{$_}->{nodeName};
67
68 # Filter
69 if (my $item_filter = $self->{options}->{$_}->{filter}) {
70 $self->{meta}->{$_}->{filter} = $item_filter;
71 }
72
73 # IdentProvider
74 if (my $item_ident = $self->{options}->{$_}->{ident}) {
75 my @item_ident = split(':', $item_ident);
76 $self->{meta}->{$_}->{IdentProvider} = { method => $item_ident[0], arg => $item_ident[1] };
77 }
78
79 # TODO: ChecksumProvider
80 # already inside {options} - get it out from there and put into {meta} here!
81
82 # exclude properties/subnodes
83 if (my $item_exclude = $self->{options}->{$_}->{exclude}) {
84 $self->{meta}->{$_}->{subnodes_exclude} = $item_exclude;
85 }
86
87 # TypeProvider
88 # FIXME! this is still Vdeprecated!!!
89 if (my $item_type = $self->{options}->{$_ . '_type'}) {
90 my @item_type = split(':', $item_type);
91 $self->{meta}->{$_}->{TypeProvider} = { method => $item_type[0], arg => $item_type[1] };
92 }
93
94 # trace
95 #print Dumper($self);
96 #exit;
97
98 # Callbacks - writers (will be triggered _before_ writing to target)
99 if (my $item_writers = $self->{options}->{$_}->{callbacks}->{write}) {
100 my $descent = $_; # this is important since the following code inside the map wants to use its own context variables
101 map { $self->{meta}->{$descent}->{Callback}->{write}->{$_}++; } @$item_writers;
102 }
103
104 # Callbacks - readers (will be triggered _after_ reading from source)
105 if (my $item_readers = $self->{options}->{$_}->{callbacks}->{read}) {
106 my $descent = $_;
107 map { $self->{meta}->{$descent}->{Callback}->{read}->{$_}++; } @$item_readers;
108 }
109
110 # resolve storage handles
111 $self->{meta}->{$_}->{storage} = $self->{options}->{$_}->{storage}->{handle};
112
113 # transfer storage handle options to metadata
114 #map { $self->{meta}->{$_}->{isIdentAuthority} = 1 } @{$self->{id_authorities}};
115 #map { $self->{meta}->{$_}->{isChecksumAuthority} = 1; } @{$self->{checksum_authorities}};
116 #map { $self->{meta}->{$_}->{isWriteProtected} = 1; } @{$self->{write_protected}};
117 #print Dumper($self->{options}->{$_});
118 #exit;
119 $self->{meta}->{$_}->{isIdentAuthority} = $self->{options}->{$_}->{storage}->{handle}->{locator}->{sync}->{isIdentAuthority};
120 $self->{meta}->{$_}->{isWriteProtected} = $self->{options}->{$_}->{storage}->{handle}->{locator}->{sync}->{isWriteProtected};
121 $self->{meta}->{$_}->{isChecksumAuthority} = $self->{options}->{$_}->{storage}->{handle}->{locator}->{sync}->{isChecksumAuthority};
122
123 }
124
125 #print Dumper($self->{meta});
126 return 1;
127
128 }
129
130
131 sub options2metadata_accessor {
132 my $self = shift;
133
134 $logger->debug( __PACKAGE__ . "->_transformMetadata_accessor" );
135
136 # build accessor metadata (for each descent)
137 foreach my $descent ('source', 'target') {
138
139 # the database type plays a role here to handle special nodesets:
140 # there may be a) childless/non-strict nodesets (e.g. a CSV-file)
141 # or b) normal ones - here the node-name corresponds more or less directly to
142 # the physical location in the storage hierarchy below us (e.g. MAPI or LDAP)
143 # or c) sets of nodes which are physically mapped by node-type (e.g. a RDBMS or a ODBMS)
144 my $dbType = $self->{meta}->{$descent}->{storage}->{locator}->{type};
145
146 # a, b and c are "accessor-type"s (of 'none', 'node-name', 'node-type')
147 # the following code resolves these types to '$accessorType'
148 # and properly sets '$accessorName'
149
150 # don't continue for certain storage handlers
151 # HACK for DBD::CSV - re-enable for other DBDs
152 #next if $dbType eq 'DBI';
153
154 # get nodename
155
156 # get node-name
157 my $nodename = $self->{meta}->{$descent}->{node}; # V1
158 $nodename ||= $self->{meta}->{$descent}->{nodeName}; # V2
159
160 # check if nodename is actually a CODEref, execute it to get a mapped/filtered target-nodename
161 #print "----", ref $nodename, "\n";
162 #if ($nodename =~ m/CODE/) {
163 # print Dumper($self);
164 # #exit;
165 # $nodename = $nodename->($nodename);
166 #}
167
168 # determine nodeset accessor -type and -name
169 # defaults
170 my $accessorType = 'none';
171 my $accessorName = '';
172
173 # if explicit address was given in options, just use it!
174 if (my $address = $self->{options}->{$descent}->{address}) {
175 $accessorType = 'direct-address';
176 $accessorName = $address;
177 }
178
179 # c)
180 elsif (($dbType eq 'DBI' || $dbType eq 'Tangram') && $self->{meta}->{$descent}->{nodeType}) {
181 $accessorType = 'node-type';
182 $accessorName = $self->{meta}->{$descent}->{nodeType};
183 }
184
185 # b)
186 elsif ($nodename) {
187 $accessorType = 'node-name';
188 $accessorName = $nodename;
189 }
190
191 # write accessor information to metadata
192 $self->{meta}->{$descent}->{accessorType} = $accessorType;
193 $self->{meta}->{$descent}->{accessorName} = $accessorName;
194
195 }
196
197 # trace
198 #print Dumper($self->{meta});
199 #print Dumper($self->{options});
200 #exit;
201
202 }
203
204
205
206 sub buildAttributeMap {
207
208 my $self = shift;
209
210 # field-structure for building sql
211 # mapping of sql-fieldnames to object-attributes
212 $self->{node}->{map} = {};
213
214 # manually set ...
215 # ... object-id
216 $self->{node}->{map}->{$self->{meta}->{target}->{IdentProvider}->{arg}} = $self->{node}->{source}->{ident};
217 # ... checksum
218 $self->{node}->{map}->{cs} = $self->{node}->{source}->{checksum};
219
220 #print "sqlmap: ", Dumper($self->{node}->{map}), "\n";
221
222 #print Dumper($self);
223 #exit;
224
225 # for transferring flat structures via simple (1:1) mapping
226 # TODO: diff per property / property value
227
228 #if ($self->{args}->{mapping}) {
229 # apply mapping from $self->{args}->{mapping} to $self->{node}->{map}
230 #foreach my $key (@{$self->{meta}->{source}->{childnodes}}) {
231 my @childnodes = @{$self->{meta}->{source}->{childnodes}};
232 for (my $mapidx = 0; $mapidx <= $#childnodes; $mapidx++) {
233 #my $map_right = $self->{args}->{mapping}->{$key};
234
235 $self->{node}->{source}->{propcache} = {};
236 $self->{node}->{target}->{propcache} = {};
237
238 # get property name
239 $self->{node}->{source}->{propcache}->{property} = $self->{meta}->{source}->{childnodes}->[$mapidx];
240 $self->{node}->{target}->{propcache}->{property} = $self->{meta}->{target}->{childnodes}->[$mapidx];
241 #print "map: $map_right", "\n";
242
243 # get property value
244 my $value;
245
246 # detect for callback - old style - (maybe the better???)
247 if (ref($self->{node}->{target}->{map}) eq 'CODE') {
248 #$value = &$map_right($objClone);
249 } else {
250 # plain (scalar?) value
251 #$value = $objClone->{$map_right};
252 $self->{node}->{source}->{propcache}->{value} = $self->{node}->{source}->{payload}->{$self->{node}->{source}->{propcache}->{property}};
253 }
254 #$self->{node}->{map}->{$key} = $value;
255
256 # detect expression
257 # for transferring deeply nested structures described by expressions
258 #print "val: $self->{node}->{source}->{propcache}->{value}", "\n";
259 if ($self->{node}->{source}->{propcache}->{property} =~ s/^expr://) {
260
261 # create an anonymous sub to act as callback target dispatcher
262 my $cb_dispatcher = sub {
263 #print "=============== CALLBACK DISPATCHER", "\n";
264 #print "ident: ", $self->{node}->{source}->{ident}, "\n";
265 #return $self->{node}->{source}->{ident};
266
267 };
268
269
270 #print Dumper($self->{node});
271
272 # build callback map for helper function
273 #my $cbmap = { $self->{meta}->{source}->{IdentProvider}->{arg} => $cb_dispatcher };
274 my $cbmap = {};
275 my $value = refexpr2perlref($self->{node}->{source}->{payload}, $self->{node}->{source}->{propcache}->{property}, $cbmap);
276 $self->{node}->{source}->{propcache}->{value} = $value;
277 }
278
279 # encode values dependent on type of underlying storage here - expand cases...
280 my $storage_type = $self->{meta}->{target}->{storage}->{locator}->{type};
281 if ($storage_type eq 'DBI') {
282 # ...for sql
283 # quotemeta?
284 $self->{node}->{source}->{propcache}->{value} = quotesql($self->{node}->{source}->{propcache}->{value});
285
286 } elsif ($storage_type eq 'Tangram') {
287 # iso? utf8 already possible?
288
289 } elsif ($storage_type eq 'LDAP') {
290 # TODO: encode utf8 here?
291
292 }
293
294 # store value to transfer map
295 $self->{node}->{map}->{$self->{node}->{target}->{propcache}->{property}} = $self->{node}->{source}->{propcache}->{value};
296
297 }
298 #}
299
300
301 # TODO: $logger->dump( ... );
302 #$logger->debug( "sqlmap:" . "\n" . Dumper($self->{node}->{map}) );
303 #print "sqlmap: ", Dumper($self->{node}->{map}), "\n";
304 #print "entrystatus: ", Dumper($self->{node}), "\n";
305
306 }
307
308 1;

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