package Connector::Multi::Merge; use strict; use warnings; use English; use Config::Merge; use Data::Dumper; use Moose; extends 'Connector::Builtin::Memory'; has '+LOCATION' => ( required => 1 ); sub _build_config { my $self = shift; # Skip the workflow directories my $cm = Config::Merge->new( $self->LOCATION() ); my $cmref = $cm->(); my $tree = $self->cm2tree($cmref); return $tree; } # Traverse the tree read from Config::Merge and replace the "@" keys by # scalar references sub cm2tree { my $self = shift; my $cm = shift; if ( ref($cm) eq 'HASH' ) { my $ret = {}; foreach my $key ( keys %{$cm} ) { if ( $key =~ m{ (?: \A @ (.*?) @ \z | \A @ (.*) | (.*?) @ \z ) }xms ) { my $match = $1 || $2 || $3; # make it a ref to an anonymous scalar so we know it's a symlink $ret->{$match} = \$cm->{$key}; } else { $ret->{$key} = $self->cm2tree( $cm->{$key} ) } } return $ret; } elsif ( ref($cm) eq 'ARRAY' ) { my $ret = []; my $i = 0; foreach my $entry ( @{$cm} ) { $ret->[ $i++ ] = $self->cm2tree($entry); } return $ret; } else { return $cm; } } 1; __DATA__ =head1 Name Connector::Multi::Merge =head1 Description This is a glue connector to create the required reference syntax for Connector::Multi based on a backend configuration handled by Config::Merge. LOCATION is passed over as path to Config::Merge and must point to the root node of the config directory. Internally, the constructor walks down the whole tree and translates all keys starting or ending with the "@" character into references as understood by Connector::Multi. =head1 CONFIGURATION There is no special configuration besides the mandatory LOCATION property. =head1 Example my $backend = Connector::Multi::Merge->new({ LOCATION = /etc/myconfigtree/ }) my $multi = Connector::Multi->new({ BASECONNECTOR => $backend })