require 5.10.0; use feature ':5.10'; use strict; use warnings; use warnings (FATAL => qw(misc numeric uninitialized)); # use autodie;

#===================================================================================================

{ package OmniTrigClass;

    use Moose;
    use MooseX::OmniTrigger;

    has foo => (is => 'rw', isa => 'Str', default => 'FOO',            omnitrigger => \&_callback);
    has bar => (is => 'rw', isa => 'Str', default => 'BAR', lazy => 1, omnitrigger => \&_callback);

    has baz => (is => 'rw', isa => 'Str', accessor => 'access_baz', reader => 'read_baz', writer => 'write_baz', clearer => 'clear_baz', omnitrigger => sub {

        my ($self) = shift;

        $self->_callback(@_);

        $self->write_baz('RECURSE, DAMN YOU');
    });

    sub _callback { say("OMNITRIGGERED FOR $_[1]") }
}

my $omnitriggered = OmniTrigClass->new;

# OMNITRIGGERED FOR foo

$omnitriggered->bar;

# OMNITRIGGERED FOR bar

$omnitriggered->meta->get_attribute('foo')->set_value($omnitriggered, 'FOO!!!');

# OMNITRIGGERED FOR foo

$omnitriggered->write_baz('BAZ???');

# OMNITRIGGERED FOR baz

say $omnitriggered->read_baz;

# RECURSE, DAMN YOU

#===================================================================================================

{ package ObservableClass;

    use Moose;

    has foo => (is => 'rw', isa => 'Str', default => 'FOO'           );
    has bar => (is => 'rw', isa => 'Str', default => 'BAR', lazy => 1);

    has baz => (is => 'rw', isa => 'Str', accessor => 'access_baz', reader => 'read_baz', writer => 'write_baz', clearer => 'clear_baz');

    # WE HAVE TO BE EXPLICIT ABOUT WHAT WE'RE OBSERVING. THIS LIST COULD GET BIG.
    with 'MooseX::Observer::Role::Observable' => {notify_after => [qw(

        foo
        bar
        access_baz
        read_baz
        write_baz
        clear_baz
    )]};
}

{ package ObserverClass;

    use Moose;
        with 'MooseX::Observer::Role::Observer';

    sub update {

        say("OBSERVED $_[3]");

        # WE HAVE TO MAINTAIN OUR OWN "DISPATCHER" HERE.
        $_[1]->write_baz('RECURSE, DAMN YOU') if $_[3] =~ /^(?:access_baz|read_baz|write_baz|clear_baz)$/;
    }
}

my $observable = ObservableClass->new;

$observable->add_observer(ObserverClass->new); # <NOTHING>

$observable->bar; # <NOTHING>

$observable->meta->get_attribute('foo')->set_value($observable, 'FOO!!!'); # <NOTHING>

$observable->write_baz('BAZ???');

# OBSERVED write_baz
# OBSERVED write_baz
# OBSERVED write_baz
# ...INIFINITE RECURSION

#===================================================================================================
