/[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.5 - (show annotations)
Fri Feb 21 08:34:58 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
Changes since 1.4: +6 -3 lines
modified object hierarchy
renamed method

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

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