614ec3618134083dccdfd34e5cd34eddae9c2c51
[scpubgit/DX.git] / lib / DX / Action / SetBoundValue.pm
1 package DX::Action::SetBoundValue;
2
3 use DX::Update::SetValue;
4 use DX::Class;
5
6 with 'DX::Role::Action';
7
8 has target_path => (is => 'ro', required => 1);
9
10 has bound_to_path => (is => 'ro', required => 1);
11
12 has rebind_path => (is => 'ro', required => 1);
13
14 has new_value => (is => 'ro', required => 1);
15
16 has inner_action => (is => 'ro', required => 1);
17
18 sub dry_run {
19   my ($self, $hyp) = @_;
20   my ($outer_hyp, @inner_events) = $self->inner_action->dry_run(
21     $hyp->but(
22       action_applications => [ @{$hyp->action_applications}, $self ],
23     ),
24   );
25   my $new_bound_to = do {
26     my $targ = $outer_hyp->scope;
27     $targ = $targ->get_member_at($_) for @{$self->bound_to_path};
28     $targ;
29   };
30   my $new_ab = DX::ActionBuilder::BoundValue->new(
31     target_path => $self->target_path,
32     rebind_path => $self->rebind_path,
33     bound_to_path => $self->bound_to_path,
34     inner_action_builder => $new_bound_to->action_builder
35   );
36   my $value_with_ab = $new_ab->apply_to_value($self->new_value, $new_bound_to);
37   my ($scope, @events) = $outer_hyp->scope->apply_updates(
38                            DX::Update::SetValue->new(
39                              target_path => $self->target_path,
40                              new_value => $value_with_ab,
41                            )
42                          );
43   my $new_bound = do {
44     my $targ = $scope;
45     $targ = $targ->get_member_at($_) for @{$self->rebind_path};
46     $targ;
47   };
48   my @actions = @{$outer_hyp->actions};
49   foreach my $idx (0.. $#actions) {
50     my $act = $actions[$idx];
51     if (
52       $act->isa('DX::Action::BindValue')
53         and join("\0", @{$act->target_path})
54               eq join("\0", @{$self->rebind_path})
55     ) {
56       my $bind = splice @actions, $idx, 1;
57       push @actions, $bind->but(new_value => $new_bound);
58       last;
59     }
60   }
61   return (
62     $outer_hyp->but(scope => $scope, actions => \@actions),
63     @inner_events, @events
64   );
65 }
66
67 sub run { die }
68
69 1;