--- nfo/perl/libs/Data/Transfer/Sync/API.pm 2003/05/13 08:16:44 1.9 +++ nfo/perl/libs/Data/Transfer/Sync/API.pm 2004/06/19 01:43:03 1.10 @@ -1,6 +1,6 @@ ## ------------------------------------------------------------------------- ## -## $Id: API.pm,v 1.9 2003/05/13 08:16:44 joko Exp $ +## $Id: API.pm,v 1.10 2004/06/19 01:43:03 joko Exp $ ## ## Copyright (c) 2002 Andreas Motl ## @@ -9,6 +9,9 @@ ## ## ------------------------------------------------------------------------- ## $Log: API.pm,v $ +## Revision 1.10 2004/06/19 01:43:03 joko +## code from _prepareOptions now split into _prepareMap and _mergeOptions +## ## Revision 1.9 2003/05/13 08:16:44 joko ## minor update: modified header ## @@ -136,6 +139,7 @@ dbKey => $self->{args_raw}->{source}, nodeType => $self->{args_raw}->{'source-type'}, nodeName => $self->{args_raw}->{'source-node'}, + ident => $self->{args_raw}->{'source-ident'}, }, target => { dbKey => $self->{args_raw}->{target}, @@ -384,97 +388,102 @@ # inform user about option preparation $logger->debug( __PACKAGE__ . "->_prepareOptions( source.node='$opts->{source}->{nodeName}', target.node='$opts->{target}->{nodeName}', mode='$opts->{process}->{mode}', e='$opts->{process}->{erase}', p='$opts->{process}->{prepare}' )"); - # try to load mapping-metadata-container - # How? Create a new instance of the given - # perl module/package name in ->{...}->{moduleName}. - # This instance is used later in the innards of the sync, - # that's why the module (class) should have a certain layout - # enabling the core to use it for gathering metadata while processing. - my $mapObject = DesignPattern::Object->fromPackage($opts->{map}->{moduleName}); + my $map = {}; + $map = $self->_prepareMap($opts) if not $opts->{process}->{prepare}; + #$map = $self->_prepareMap($opts); + + # merge all together + $self->_mergeOptions($opts, $map); + #print Dumper($self->{options}); - # try to resolve map from metadata-container + $self->{state}->{options_ready} = 1; - # type of the item/node - my $source_nodeType = $opts->{source}->{nodeType}; - - # check if mapping for certain node is contained in mapping object - if (!$mapObject || !$mapObject->can($source_nodeType)) { - $logger->warning( __PACKAGE__ . "->_prepareOptions: Can't access mapping for source-type=\"$source_nodeType\" - please check \"$opts->{map}->{moduleName}\"."); - return; - } + return 1; - # get map - my $map = $mapObject->$source_nodeType; - #print Dumper($map); +} + +sub _prepareMap { + my $self = shift; + my $opts = shift; - my $map_version = $map->{metadata}->{version}; - # FIXME: backward compatibility - if (!$map_version) { - $self->options_to_V2($map); - } + # 1. try to load mapping-metadata-container + + # How? Create a new instance of the given + # perl module/package name in ->{...}->{moduleName}. + # This instance is used later in the innards of the sync, + # that's why the module (class) should have a certain layout + # enabling the core to use it for gathering metadata while processing. + my $mapObject = DesignPattern::Object->fromPackage($opts->{map}->{moduleName}); - # trace - #print Dumper($map); - #exit; - #print "ref: ", ref $map->{target}, "\n"; - #print "target: ", $map->{target}, "\n"; - - # check here if "target" is actually a CODEref - in this case: resolve it - deprecated!!! ??? - if (ref $map->{target}->{address} eq 'CODE') { - $map->{target}->{address} = $map->{target}->{address}->($source_nodeType); - } - - # resolve expressions (on nodename-level) here - elsif ($map->{target}->{address} =~ m/^(code|expr):(.+?)$/) { - my $target_dynamic_type = $1; - my $target_dynamic_expression = $2; - if (lc $target_dynamic_type eq 'code') { - $map->{target} = $mapObject->$target_dynamic_expression($map); - } - } - # merging - V1 - #map { $opts->{$_} = $map->{$_}; } keys %$map; - # trace - #print Dumper($self->{options}); + # 2. try to resolve map from metadata-container + + # type of the item/node + my $source_nodeType = $opts->{source}->{nodeType}; - # merging - V2 + # check if mapping for certain node is contained in mapping object + if (!$mapObject || !$mapObject->can($source_nodeType)) { + $logger->warning( __PACKAGE__ . "->_prepareOptions: Can't access mapping for source-type=\"$source_nodeType\" - please check \"$opts->{map}->{moduleName}\"."); + return; + } - # merge local map with local opts - - # delete undef'd items in $map - - # enable cloning - # FIXME: do we really need cloning here? trade safety/encapsulation for speed? - Hash::Merge::set_clone_behavior(1); - Hash::Merge::set_behavior( 'RIGHT_PRECEDENT' ); - #Hash::Merge::set_behavior( 'STORAGE_PRECEDENT' ); - #Hash::Merge::set_behavior( 'RETAINMENT_PRECEDENT' ); - # TODO: add an option to Hash::Merge not to overwrite set items with undefined/empty/not assigned ones - my $locals_merged = merge( $opts, $map ); - - # trace - #print Dumper($opts); - #print Dumper($map); - #print Dumper($locals_merged); - #exit; + # get map + my $map = $mapObject->$source_nodeType; + #print Dumper($map); + + my $map_version = $map->{metadata}->{version}; + # FIXME: backward compatibility + if (!$map_version) { + $self->options_to_V2($map); + } - # merge local-merged ones with instance-wide options - Hash::Merge::set_clone_behavior(0); - $self->{options} = merge( $self->{options}, $locals_merged ); + # trace + #print Dumper($map); + #exit; + #print "ref: ", ref $map->{target}, "\n"; + #print "target: ", $map->{target}, "\n"; - # trace - #print Dumper($self->{options}); - #exit; + # check here if "target" is actually a CODEref - in this case: resolve it - deprecated!!! ??? + if (ref $map->{target}->{address} eq 'CODE') { + $map->{target}->{address} = $map->{target}->{address}->($source_nodeType); + } + # resolve expressions (on nodename-level) here + elsif ($map->{target}->{address} =~ m/^(code|expr):(.+?)$/) { + my $target_dynamic_type = $1; + my $target_dynamic_expression = $2; + if (lc $target_dynamic_type eq 'code') { + $map->{target} = $mapObject->$target_dynamic_expression($map); + } + } + + return $map; + +} - $self->{state}->{options_ready} = 1; +sub _mergeOptions { + my $self = shift; + my $opts = shift; + my $map = shift; - return 1; + # 1. merge local map with local opts + + # delete undef'd items in $map + # enable cloning + # FIXME: do we really need cloning here? trade safety/encapsulation for speed? + Hash::Merge::set_clone_behavior(1); + Hash::Merge::set_behavior( 'RIGHT_PRECEDENT' ); + #Hash::Merge::set_behavior( 'STORAGE_PRECEDENT' ); + #Hash::Merge::set_behavior( 'RETAINMENT_PRECEDENT' ); + # TODO: add an option to Hash::Merge not to overwrite set items with undefined/empty/not assigned ones + my $locals_merged = merge( $opts, $map ); + + # 2. merge local-merged ones with instance-wide options + Hash::Merge::set_clone_behavior(0); + $self->{options} = merge( $self->{options}, $locals_merged ); } - sub _preCheckOptions { my $self = shift; @@ -484,8 +493,8 @@ #print Dumper($opts); #exit; - if (!$opts->{process}->{mode}) { - $logger->error( __PACKAGE__ . "->_preCheckOptions failed: Please specify \"--action=(load|save)\"."); + if (!$opts->{process}->{mode} and !$opts->{process}->{prepare}) { + $logger->error( __PACKAGE__ . "->_preCheckOptions failed: Please specify \"--action=(load|save)\" or \"--prepare\"."); return; } @@ -505,7 +514,7 @@ $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}) { + if (!$opts->{map}->{moduleName} and !$opts->{process}->{prepare}) { $logger->warning( __PACKAGE__ . "->_preCheckOptions: Currently only perl-modules can provide mappings: Please specify one with '--mapping-module=My::Mapping::Module'."); return; } @@ -554,7 +563,7 @@ if ($self->{options}->{process}->{prepare}) { $self->_prepareNode_MetaProperties('source'); $self->_prepareNode_DummyIdent('source'); - #return; + return; #$self->_erase_all($opts->{source_node}); }