=head1 NAME SuikaWiki::DB::Logical --- SuikaWiki WikiDatabase: Logical database consists of multiple datasources =head1 DESCRIPTION This module provides a logical database implementation. It does not itself have physical datasource at all. With database property name asspcoatopms, multiple database instances that have common WikiDatabase interface can be used as datasources. This module is part of SuikaWiki. =cut package SuikaWiki::DB::Logical; require SuikaWiki::DB::Util; sub new ($%) { my ($class, %o) = @_; my $self = bless {}, $class; if ($o{-lock}) { $self->{lock} = SuikaWiki::DB::Util->new_lock ($self->{-lock}); $self->{lock}->lock; } $self->{prop} = undef; $self->{error} = SuikaWiki::DB::Util->error_handler; $self; } sub get ($$$) { my ($self, $prop, $key) = @_; if ($self->{prop}->{$prop}) { return $self->{prop}->{$prop}->{-db}->get ($self->{prop}->{$prop}->{-prop}, &{$self->{prop}->{$prop}->{-key_mapper}} ($key)); } else { return undef; } } sub set ($$$$) { my ($self, $prop, $key => $value) = @_; if ($self->{prop}->{$prop}) { $self->{prop}->{$prop}->{-db}->set ($self->{prop}->{$prop}->{-prop}, &{$self->{prop}->{$prop}->{-key_mapper}} ($key) => $value); } else { $self->{error}->raise (type => 'KEY_SAVE', key => $key); } } sub exist ($$$) { my ($self, $prop, $key) = @_; if ($self->{prop}->{$prop}) { return $self->{prop}->{$prop}->{-db}->exist ($self->{prop}->{$prop}->{-prop}, &{$self->{prop}->{$prop}->{-key_mapper}} ($key)); } else { return 0; } } sub delete ($$$) { my ($self, $prop, $key) = @_; if ($self->{prop}->{$prop}) { $self->{prop}->{$prop}->{-db}->delete ($self->{prop}->{$prop}->{-prop}, &{$self->{prop}->{$prop}->{-key_mapper}} ($key)); } } sub keys ($$;%) { my ($self, $prop, %opt) = @_; if ($self->{prop}->{$prop}) { $opt{-ns} = &{$self->{prop}->{$prop}->{-key_mapper}} ($opt{-ns}); return map {&{$self->{prop}->{$prop}->{-key_rev_mapper}} ($_)} $self->{prop}->{$prop}->{-db}->keys ($self->{prop}->{$prop}->{-prop}, %opt); } else { return (); } } sub close ($) { my $self = shift; $self->{prop} = undef; } sub DESTROY ($) { my $self = shift; $self->close if $self->{prop}; } =head1 METHODS This module provides common interface of SuikaWiki WikiDatabase modules. See documentation of C. In addition, this module implements additional methods. =over 4 =item _set_prop_db ($prop_name, {options}) Addosiates actual database with property name of this logical (virtual) database, or remove its association by specifying C instead of C<{options}>. Options: =over 4 =item -db => $database_instance (REQUIRED) Instance of database module, which implements common WikiDatabase interface. =item -prop => $property_name (Default: same as $prop_name) Property name used to access to $database_instance. With this option, different property name from datasource's one can be used, eg. maps $prop_name eq 'subdb_foo' to $property_name eq 'foo'. =item -key_mapper => sub ($self, $key) (Default: sub {$key}) Mapper from this virtual database's keyname to sub database's one. =item -key_rev_mapper => sub ($self, $key) (Default: sub {$key}) Mapper from sub database's keyname to this virtual database's keyname. Note that -key_mapper (-key_rev_mapper ($key)) need not equal to $key, although it seems an unusual case. =back =cut sub _set_prop_db ($$$) { my ($self, $prop, $db_and_opt) = @_; $self->{prop}->{$prop} = $db_and_opt; $db_and_opt->{-prop} = $prop unless defined $db_and_opt->{-prop}; $db_and_opt->{-key_mapper} ||= \&__default_key_mapper; $db_and_opt->{-key_rev_mapper} ||= \&__default_key_rev_mapper; } sub __default_key_mapper ($$) { #my ($self, $key) = @_; #$key; $_[1]; } sub __default_key_rev_mapper ($$) { #my ($self, $key) = @_; #$key; $_[1]; } =back =head1 AUTHOR Wakaba . =head1 LICENSE Copyright 2003 Wakaba This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; # $Date: 2003/08/06 01:26:14 $