Anansi-ComponentManager

 view release on metacpan or  search on metacpan

lib/Anansi/ComponentManager.pm  view on Meta::CPAN

package Anansi::ComponentManager;


=head1 NAME

Anansi::ComponentManager - A base module definition for related process management.

=head1 SYNOPSIS

    package Anansi::ComponentManagerExample;

    use base qw(Anansi::ComponentManager);

    sub doSomethingElse {
        my ($self, $channel, %parameters) = @_;
    }

    Anansi::ComponentManager::addChannel(
        'Anansi::ComponentManagerExample',
        'SOME_MANAGER_CHANNEL' => Anansi::ComponentManagerExample->doSomethingElse
    );

    1;

    package Anansi::ComponentManagerExample::ComponentExample;

    use base qw(Anansi::Component);

    sub priority {
        my ($self, $channel, %parameters) = @_;
        my $PRIORITY = {
            'Anansi::ComponentManagerExample::AnotherComponentExample' => 'HIGHER',
            'Anansi::ComponentManagerExample::YetAnotherComponentExample' => 'LOWER',
            'Anansi::ComponentManagerExample::SomeOtherComponentExample' => 'SAME',
            'Anansi::ComponentManagerExample::ADifferentComponentExample' => 1,
            'Anansi::ComponentManagerExample::EtcComponentExample' => 0,
            'Anansi::ComponentManagerExample::AndSoOnComponentExample' => -1,
        };
        return $PRIORITY;
    }

    sub validate {
        my ($self, $channel, %parameters) = @_;
        return 1;
    }

    sub doSomething {
        my ($self, $channel, %parameters) = @_;
    }

    Anansi::Component::addChannel(
        'Anansi::ComponentManagerExample::ComponentExample',
        'PRIORITY_OF_VALIDATE' => Anansi::ComponentManagerExample::ComponentExample->priority
    );
    Anansi::Component::addChannel(
        'Anansi::ComponentManagerExample::ComponentExample',
        'VALIDATE_AS_APPROPRIATE' => Anansi::ComponentManagerExample::ComponentExample->validate
    );
    Anansi::Component::addChannel(
        'Anansi::ComponentManagerExample::ComponentExample',
        'SOME_COMPONENT_CHANNEL' => Anansi::ComponentManagerExample::ComponentExample->doSomething
    );

    1;

    package main;

    use Anansi::ComponentManagerExample;

    my $object = Anansi::ComponentManagerExample->new();
    my $component = $object->addComponent();
    my $result = $object->channel(
        $component,
        'SOME_COMPONENT_CHANNEL',
        someParameter => 'some data',
        anotherParameter => 'some more data',
    );

    my $another = Anansi::ComponentManagerExample->new(
        IDENTIFICATION => 'Another component',
    );
    $result = $object->channel(
        'Another component',
        'SOME_COMPONENT_CHANNEL',
        aParameter => 'more data?',
    );

    1;

=head1 DESCRIPTION

This is a base module definition for the management of modules that deal with
related functionality.  This management module provides the mechanism to handle
multiple related functionality modules at the same time, loading and creating an
object of the most appropriate module to handle each situation by using the
VALIDATE_AS_APPROPRIATE and PRIORITY_OF_VALIDATE component channels.  In order
to simplify the recognition of related L<Anansi::Component> modules, each
component is required to have the same base namespace as it's manager.

=cut


our $VERSION = '0.10';

use base qw(Anansi::Singleton);

use Anansi::Actor;

my %CHANNELS;
my %COMPONENTS;
my %IDENTIFICATIONS;
my %PRIORITIES;


=head1 METHODS

=cut

lib/Anansi/ComponentManager.pm  view on Meta::CPAN

                ${$CHANNELS{$package}}{$key} = sub {
                    my ($self, $channel, @PARAMETERS) = @_;
                    return &{\&{$package.'::'.$parameters{$key}}}($self, $channel, (@PARAMETERS));
                };
            }
        }
    }
    return 1;
}


=head2 addComponent

    my $identification = Anansi::ComponentManager->addComponent(
        undef,
        someParameter => 'some value'
    );
    if(defined($identification));

    my $identification = $OBJECT->addComponent(
        undef,
        someParameter => 'some value'
    );
    if(defined($identification));

    my $identification = Anansi::ComponentManager->addComponent(
        'some identifier',
        someParameter => 'some value'
    );
    if(defined($identification));

    my $identification = $OBJECT->addComponent(
        'some identifier',
        someParameter => 'some value'
    );
    if(defined($identification));

=over 4

=item self I<(Blessed Hash B<or> String, Required)>

An object or string of this namespace.

=item identification I<(String, Required)>

The name to associate with the component.

=item parameters I<(Scalar B<or> Array, Optional)>

The list of parameters to pass to the I<VALIDATE_AS_APPROPRIATE> channel of
every component module found on the system.

=back

Creates a new component object and stores the object for indirect interaction by
the implementer of the component manager.  A unique identifier for the object
may either be supplied or automatically generated and is returned as a means of
referencing the object.

Note: The process of selecting the component to use requires each component to
validate it's own appropriateness.  Therefore this process makes use of a
VALIDATE_AS_APPROPRIATE component channel which is expected to return either a
B<1> I<(one)> or a B<0> I<(zero)> representing B<appropriate> or
B<inappropriate>.  If this component channel does not exist it is assumed that
the component is not designed to be implemented in this way.  A component may
also provide a PRIORITY_OF_VALIDATE component channel to aid in validating where
multiple components may be appropriate to different degrees.  If this component
channel does not exist it is assumed that the component has the lowest priority.

=cut


sub addComponent {
    my ($self, $identification, @parameters) = @_;
    my $package = $self;
    $package = ref($self) if(ref($self) !~ /^$/);
    if(!defined($identification)) {
        $identification = $self->componentIdentification();
    } elsif(ref($identification) !~ /^$/) {
        return;
    } elsif($identification =~ /^\s*$/) {
        return;
    } elsif(defined($COMPONENTS{$package})) {
        return $identification if(defined(${$COMPONENTS{$package}}{$identification}));
        my %reverse = map { ${$COMPONENTS{$package}}{$_} => $_ } (keys(%{$COMPONENTS{$package}}));
        return $reverse{$identification} if(defined($reverse{$identification}));
        return if(defined($IDENTIFICATIONS{$identification}));
        %reverse = map { $IDENTIFICATIONS{$_} => $_ } (keys(%IDENTIFICATIONS));
        return if(defined($reverse{$identification}));
    }
    my $alias = '';
    if($identification !~ /^\d{20}$/) {
        $alias = $identification;
        $identification = $self->componentIdentification();
    }
    my $components = $self->components();
    return if(ref($components) !~ /^ARRAY$/i);
    my $priority = $self->priorities(
        PARAMETERS => [(@parameters)],
    );
    return if(!defined($priority));
    my $OBJECT;
    while(0 <= $priority) {
        my $components = $self->priorities(
            PRIORITY => $priority,
        );
        next if(!defined($components));
        next if(ref($components) !~ /^ARRAY$/i);
        foreach my $component (@{$components}) {
            my $valid = &{\&{'Anansi::Component::channel'}}($component, 'VALIDATE_AS_APPROPRIATE', (@parameters));
            next if(!defined($valid));
            if($valid) {
                $OBJECT = Anansi::Actor->new(PACKAGE => $component, (@parameters));
                last;
            }
        }
        last if(defined($OBJECT));
        $priority--;
    }
    return if(!defined($OBJECT));
    $COMPONENTS{$package} = {} if(!defined($COMPONENTS{$package}));



( run in 0.980 second using v1.01-cache-2.11-cpan-13bb782fe5a )