--- nfo/perl/libs/Data/Transfer/Sync/Metadata.pm 2003/01/20 16:58:46 1.1 +++ nfo/perl/libs/Data/Transfer/Sync/Metadata.pm 2003/05/13 08:13:25 1.7 @@ -1,11 +1,34 @@ -## $Id: Metadata.pm,v 1.1 2003/01/20 16:58:46 joko Exp $ +## ------------------------------------------------------------------------- +## +## $Id: Metadata.pm,v 1.7 2003/05/13 08:13:25 joko Exp $ ## ## Copyright (c) 2002 Andreas Motl ## -## See COPYRIGHT section in pod text below for usage and distribution rights. +## See COPYRIGHT section in associated pod text +## or below for usage and distribution rights. ## -## ---------------------------------------------------------------------------------------- +## ------------------------------------------------------------------------- ## $Log: Metadata.pm,v $ +## Revision 1.7 2003/05/13 08:13:25 joko +## moved "sub buildAttributeMap" to Map.pm +## +## Revision 1.6 2003/03/28 03:08:17 joko +## fix regarding namespace update +## +## Revision 1.5 2003/02/21 08:34:58 joko +## modified object hierarchy +## renamed method +## +## Revision 1.4 2003/02/14 14:06:20 joko +## + minor fix to old metadata structure +## +## Revision 1.3 2003/02/11 06:28:24 joko +## + changes to metadata structure +## +## Revision 1.2 2003/02/09 05:02:05 joko +## + major structure changes +## - refactored code to sister modules +## ## Revision 1.1 2003/01/20 16:58:46 joko ## + initial check-in: here they are.... ## @@ -23,119 +46,24 @@ use mixin::with qw( Data::Transfer::Sync ); -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - main +use Data::Dumper; # get logger instance my $logger = Log::Dispatch::Config->instance; -use Data::Dumper; - - -sub _preCheckOptions { - - my $self = shift; - my $opts = shift; - -#print Dumper($opts); -#exit; - - # the type of the to-be-synced item - if (!$opts->{source}->{nodeType}) { - $logger->error( __PACKAGE__ . "->_preCheckOptions failed: Please specify \"source-type\"."); - return; - } - # the name of the (container-) node the items are listed in - if (!$opts->{source}->{nodeName}) { - $logger->error( __PACKAGE__ . "->_preCheckOptions failed: Please specify \"source-node\"."); - return; - } - - # a "map"-declaration which module to use for mapping- and/or lookup-purposes - if (!$opts->{map}) { - $logger->warning( __PACKAGE__ . "->_preCheckOptions: No mapping supplied - please check key 'map|mappings' in global configuration or specify additional argument '--mapping-module'."); - return; - } - if (!$opts->{map}->{moduleName}) { - $logger->warning( __PACKAGE__ . "->_preCheckOptions: Currently only perl-modules can provide mappings: Please specify one with '--mapping-module'."); - return; - } - - return 1; - -} - -# TODO: refactor!!! take this list from already established/given metadata -sub _buildMetadataV1 { - my $self = shift; - - # decompose identifiers for each partner - foreach ('source', 'target') { - - # get/set metadata for further processing - - # Partner and Node (e.g.: "L:Country" or "R:countries.csv") - if (my $item = $self->{args}->{$_}) { - my @item = split(':', $item); - $self->{meta}->{$_}->{dbkey} = $item[0]; - $self->{meta}->{$_}->{node} = $item[1]; - } - - # Filter - if (my $item_filter = $self->{args}->{$_ . '_filter'}) { - $self->{meta}->{$_}->{filter} = $item_filter; - } - - # IdentProvider - if (my $item_ident = $self->{args}->{$_ . '_ident'}) { - my @item_ident = split(':', $item_ident); - $self->{meta}->{$_}->{IdentProvider} = { method => $item_ident[0], arg => $item_ident[1] }; - } - -#print Dumper($self->{meta}); - - # TODO: ChecksumProvider - - # exclude properties/subnodes - if (my $item_exclude = $self->{args}->{$_ . '_exclude'}) { - $self->{meta}->{$_}->{subnodes_exclude} = $item_exclude; - } - - # TypeProvider - if (my $item_type = $self->{args}->{$_ . '_type'}) { - my @item_type = split(':', $item_type); - $self->{meta}->{$_}->{TypeProvider} = { method => $item_type[0], arg => $item_type[1] }; - } - - # Callbacks - writers (will be triggered _before_ writing to target) - if (my $item_writers = $self->{args}->{$_ . '_callbacks_write'}) { - my $descent = $_; # this is important since the following code inside the map wants to use its own context variables - map { $self->{meta}->{$descent}->{Callback}->{write}->{$_}++; } @$item_writers; - } - - # Callbacks - readers (will be triggered _after_ reading from source) - if (my $item_readers = $self->{args}->{$_ . '_callbacks_read'}) { - my $descent = $_; - map { $self->{meta}->{$descent}->{Callback}->{read}->{$_}++; } @$item_readers; - } - - # resolve storage objects - #$self->{$_} = $self->{container}->{storage}->{$self->{meta}->{$_}->{dbkey}}; - # relink references to metainfo - $self->{meta}->{$_}->{storage} = $self->{container}->{storage}->{$self->{meta}->{$_}->{dbkey}}; - #print "iiiiisprov: ", Dumper($self->{meta}->{$_}->{storage}), "\n"; - } - -} - - # TODO: refactor (still)!!! take this list from already established/given metadata .... # .... also internally: passing around and mungling these metadata doesn't make sense anymore. -sub _buildMetadataV2 { +sub options2metadata { my $self = shift; -#print Dumper($self->{options}); + $logger->debug( __PACKAGE__ . "->transformMetadata" ); + + # trace + #print Dumper($self->{options}); + #print Dumper($self->{args_raw}); + #exit; - # decompose identifiers for each partner + # decompose identifiers and write to metadata (for each descent) foreach ('source', 'target') { # get/set metadata for further processing @@ -144,13 +72,13 @@ $self->{options}->{$_}->{nodeType} ||= ''; $self->{options}->{$_}->{nodeName} ||= ''; - # Partner and Node (e.g.: "L:Country" or "R:countries.csv") + # Partner and Node (compare the V1-notations: "L:Country" or "R:countries.csv") $self->{meta}->{$_}->{dbKey} = $self->{options}->{$_}->{dbKey}; $self->{meta}->{$_}->{nodeType} = $self->{options}->{$_}->{nodeType}; $self->{meta}->{$_}->{nodeName} = $self->{options}->{$_}->{nodeName}; # Filter - if (my $item_filter = $self->{args}->{$_ . '_filter'}) { + if (my $item_filter = $self->{options}->{$_}->{filter}) { $self->{meta}->{$_}->{filter} = $item_filter; } @@ -161,6 +89,7 @@ } # TODO: ChecksumProvider + # already inside {options} - get it out from there and put into {meta} here! # exclude properties/subnodes if (my $item_exclude = $self->{options}->{$_}->{exclude}) { @@ -168,25 +97,41 @@ } # TypeProvider - if (my $item_type = $self->{args}->{$_ . '_type'}) { + # FIXME! this is still Vdeprecated!!! + if (my $item_type = $self->{options}->{$_ . '_type'}) { my @item_type = split(':', $item_type); $self->{meta}->{$_}->{TypeProvider} = { method => $item_type[0], arg => $item_type[1] }; } + + # trace + #print Dumper($self); + #exit; # Callbacks - writers (will be triggered _before_ writing to target) - if (my $item_writers = $self->{args}->{$_ . '_callbacks_write'}) { + if (my $item_writers = $self->{options}->{$_}->{callbacks}->{write}) { my $descent = $_; # this is important since the following code inside the map wants to use its own context variables map { $self->{meta}->{$descent}->{Callback}->{write}->{$_}++; } @$item_writers; } # Callbacks - readers (will be triggered _after_ reading from source) - if (my $item_readers = $self->{args}->{$_ . '_callbacks_read'}) { + if (my $item_readers = $self->{options}->{$_}->{callbacks}->{read}) { my $descent = $_; map { $self->{meta}->{$descent}->{Callback}->{read}->{$_}++; } @$item_readers; } - # resolve storage objects - $self->{meta}->{$_}->{storage} = $self->{options}->{$_}->{storage}->{handle}; + # resolve storage handles + $self->{meta}->{$_}->{storage} = $self->{options}->{$_}->{storage}->{handle}; + + # transfer storage handle options to metadata + #map { $self->{meta}->{$_}->{isIdentAuthority} = 1 } @{$self->{id_authorities}}; + #map { $self->{meta}->{$_}->{isChecksumAuthority} = 1; } @{$self->{checksum_authorities}}; + #map { $self->{meta}->{$_}->{isWriteProtected} = 1; } @{$self->{write_protected}}; + #print Dumper($self->{options}->{$_}); + #exit; + $self->{meta}->{$_}->{isIdentAuthority} = $self->{options}->{$_}->{storage}->{handle}->{locator}->{sync}->{isIdentAuthority}; + $self->{meta}->{$_}->{isWriteProtected} = $self->{options}->{$_}->{storage}->{handle}->{locator}->{sync}->{isWriteProtected}; + $self->{meta}->{$_}->{isChecksumAuthority} = $self->{options}->{$_}->{storage}->{handle}->{locator}->{sync}->{isChecksumAuthority}; + } #print Dumper($self->{meta}); @@ -195,37 +140,79 @@ } -sub _buildFieldmappingV1 { +sub options2metadata_accessor { my $self = shift; - # build mapping - # incoming: and Array of node map entries (Array or Hash) - e.g. - # [ 'source:item_name' => 'target:class_val' ] - # { source => 'event->startDateTime', target => 'begindate' } - foreach (@{$self->{args}->{mapping}}) { - if (ref $_ eq 'ARRAY') { - my @entry1 = split(':', $_->[0]); - my @entry2 = split(':', $_->[1]); - my $descent = []; - my $node = []; - $descent->[0] = $entry1[0]; - $descent->[1] = $entry2[0]; - $node->[0] = $entry1[1]; - $node->[1] = $entry2[1]; - push @{$self->{meta}->{$descent->[0]}->{childnodes}}, $node->[0]; - push @{$self->{meta}->{$descent->[1]}->{childnodes}}, $node->[1]; - } elsif (ref $_ eq 'HASH') { - foreach my $entry_key (keys %$_) { - my $entry_val = $_->{$entry_key}; - push @{$self->{meta}->{$entry_key}->{childnodes}}, $entry_val; - } - } + $logger->debug( __PACKAGE__ . "->_transformMetadata_accessor" ); - } + # build accessor metadata (for each descent) + foreach my $descent ('source', 'target') { - return 1; + # the database type plays a role here to handle special nodesets: + # there may be a) childless/non-strict nodesets (e.g. a CSV-file) + # or b) normal ones - here the node-name corresponds more or less directly to + # the physical location in the storage hierarchy below us (e.g. MAPI or LDAP) + # or c) sets of nodes which are physically mapped by node-type (e.g. a RDBMS or a ODBMS) + my $dbType = $self->{meta}->{$descent}->{storage}->{locator}->{type}; + + # a, b and c are "accessor-type"s (of 'none', 'node-name', 'node-type') + # the following code resolves these types to '$accessorType' + # and properly sets '$accessorName' + + # don't continue for certain storage handlers + # HACK for DBD::CSV - re-enable for other DBDs + #next if $dbType eq 'DBI'; + + # get nodename + + # get node-name + my $nodename = $self->{meta}->{$descent}->{node}; # V1 + $nodename ||= $self->{meta}->{$descent}->{nodeName}; # V2 + + # check if nodename is actually a CODEref, execute it to get a mapped/filtered target-nodename + #print "----", ref $nodename, "\n"; + #if ($nodename =~ m/CODE/) { + # print Dumper($self); + # #exit; + # $nodename = $nodename->($nodename); + #} + + # determine nodeset accessor -type and -name + # defaults + my $accessorType = 'none'; + my $accessorName = ''; + + # if explicit address was given in options, just use it! + if (my $address = $self->{options}->{$descent}->{address}) { + $accessorType = 'direct-address'; + $accessorName = $address; + } + + # c) + elsif (($dbType eq 'DBI' || $dbType eq 'Tangram') && $self->{meta}->{$descent}->{nodeType}) { + $accessorType = 'node-type'; + $accessorName = $self->{meta}->{$descent}->{nodeType}; + } + + # b) + elsif ($nodename) { + $accessorType = 'node-name'; + $accessorName = $nodename; + } + + # write accessor information to metadata + $self->{meta}->{$descent}->{accessorType} = $accessorType; + $self->{meta}->{$descent}->{accessorName} = $accessorName; + + } + + # trace + #print Dumper($self->{meta}); + #print Dumper($self->{options}); + #exit; } 1; +__END__