pervasive type constraints
[scpubgit/DX.git] / lib / DX / ActionBuilder / Normal.pm
1 package DX::ActionBuilder::Normal;
2
3 use DX::Action::SetValue;
4 use DX::Action::AddValue;
5 use DX::Utils qw(:event_types);
6 use DX::Class;
7
8 with 'DX::Role::ActionBuilder';
9
10 has target_path => (is => 'ro', required => 1, isa => ValuePath);
11
12 sub aperture_for_set_value {
13   [ [ VALUE_SET ,=> @{$_[0]->target_path} ] ]
14 }
15
16 sub action_for_set_value {
17   my ($self, $value) = @_;
18   DX::Action::SetValue->new(
19     target_path => $self->target_path,
20     new_value => $self->apply_to_value($value),
21   );
22 }
23
24 sub aperture_for_add_member {
25   my ($self, $at) = @_;
26   [ [ VALUE_EXISTS ,=> @{$self->target_path}, $at ] ]
27 }
28
29 sub action_for_add_member {
30   my ($self, $at, $value) = @_;
31   my $ab = $self->specialize_for_member($at);
32   DX::Action::AddValue->new(
33     target_path => $ab->target_path,
34     new_value => $ab->apply_to_value($value),
35   );
36 }
37
38 sub action_for_remove_member { die 'WHUT' }
39
40 sub apply_to_value {
41   my ($self, $value) = @_;
42   my $new_value = $value->but_set_action_builder($self);
43   return $new_value unless $new_value->isa('DX::Value::Dict');
44   my %m = %{$new_value->members};
45   return $new_value->but(
46     members => {
47       map +($_ => $self->specialize_for_member($_)->apply_to_value($m{$_})),
48         keys %m,
49     },
50   );
51 }
52
53 sub specialize_for_member {
54   my ($self, $at) = @_;
55   $self->but(
56     target_path => [
57       @{$self->target_path},
58       (ref($at) ? $at->string_value : $at)
59     ],
60   );
61 }
62
63 1;