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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations)
Sun Feb 9 05:02:05 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.1: +180 -126 lines
+ major structure changes
- refactored code to sister modules

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

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