package DBIx::DataModel::Meta::Path; use strict; use warnings; use parent "DBIx::DataModel::Meta"; use DBIx::DataModel; use DBIx::DataModel::Meta::Utils qw/define_readonly_accessors/; use Scalar::Util qw/looks_like_number weaken/; use Params::Validate qw/validate_with SCALAR HASHREF ARRAYREF OBJECT/; use Carp::Clan qw[^(DBIx::DataModel::|SQL::Abstract)]; use namespace::clean; {no strict 'refs'; *CARP_NOT = \@DBIx::DataModel::CARP_NOT;} my $path_spec = { name => {type => SCALAR}, from => {isa => 'DBIx::DataModel::Meta::Source::Table'}, to => {isa => 'DBIx::DataModel::Meta::Source::Table'}, on => {type => HASHREF}, # join condition multiplicity => {type => ARRAYREF}, association => {type => OBJECT, isa => "DBIx::DataModel::Meta::Association"}, direction => {type => SCALAR, regex => qr/^(AB|BA)$/}, }; sub new { my $class = shift; # parse arguments and create $self my $self = validate_with( params => \@_, spec => $path_spec, allow_extra => 0, ); my $path = $self->{name}; weaken $self->{$_} for qw/from to association/; # add this path into the 'from' metaclass not $self->{from}{path}{$path} or croak "$self->{from}{class} already has a path '$path'"; $self->{from}{path}{$path} = $self; push @{$self->{from}{components}}, $path if $self->{association}{kind} eq 'Composition'; # install a navigation method into the 'from' table class my @navigation_args = ($self->{name}, # method name $self->{name}); # path to follow push @navigation_args, {-result_as => "firstrow"} if $self->{multiplicity}[1] == 1; $self->{from}->define_navigation_method(@navigation_args); bless $self, $class; } define_readonly_accessors(__PACKAGE__, keys %$path_spec); sub opposite { my $self = shift; my $opposite_direction = reverse $self->direction; my $opposite_path = "path_".$opposite_direction; return $self->association->$opposite_path; } 1; __END__ =head1 NAME DBIx::DataModel::Meta::Path - meta-information about a path =head1 SYNOPSIS # create the path; best called through $assoc->_install_path(...) my $path = new ( name => $role_name, from => $source_meta_table, to => $destination_meta_table, on => \%condition, # in SQL::Abstract::More format multiplicity => [$min, $max], association => $association, direction => $direction, # either 'AB' or 'BA' ); =head1 DESCRIPTION This class is closely related to L<DBIx::DataModel::Meta::Association>. A I<path> corresponds to one possible database join between two tables. =head1 PUBLIC METHODS =head2 new Constructor method. Normally this will be called indirectly through $association->_install_path(%args) because the L<DBIx::DataModel::Meta::Association/_install_path> method automatically adds its own invocant (the C<$association>) into C<%args>. Named arguments to C<new()> are : =over =item name The name of this path (must be unique within the source table). That name is used for defining a Perl method in the class associated to the source table, and for interpreting multi-steps joins in calls like $schema->join(qw/FirstTable role1 role2 .../) =item from The L<DBIx::DataModel::Meta::Source::Table> instance which is the source for this path. =item to The L<DBIx::DataModel::Meta::Source::Table> instance which is the target for this path. =item on A hashref that describes the database join condition : the keys are names of columns for the left-hand side, and values are names of columns for the right-hand side. For example on => {foreign_1 => 'primary_1', foreign_2 => 'primary_2'} will generate SQL clauses of shape .. JOIN ON <left>.foreign_1 = <right>.primary_1 AND <left>.foreign_2 = <right>.primary_2 =item multiplicity An arrayref C<< [$min, $max] >>; see explanations in L<DBIx::DataModel::Meta::Association>. =item association The association to which this path belongs. =item direction A string that describes the direction of this path within the association : must be either C<'AB'> or C<'BA'>. =back =head2 name Name of this path =head2 from Source of this path (an instance of L<DBIx::DataModel::Meta::Source::Table>). =head2 to Target of this path (an instance of L<DBIx::DataModel::Meta::Source::Table>). =head2 on Copy of the hash for the join condition =head2 multiplicity Array C<($min, $max)> describing the multiplicity. =head2 association Instance of L<DBIx::DataModel::Meta::Association> to which this path belongs. =head2 direction Direction of the path within the association; a string containing either C<'AB'> or C<'BA'>. =head2 opposite Returns the path object representing the opposite direction. =cut