refactor action stuff to be recursive on dicts
[scpubgit/DX.git] / lib / DX / ActionBuilder / Normal.pm
index c950758..45e5abd 100644 (file)
@@ -12,22 +12,43 @@ sub action_for_set_value {
   my ($self, $value) = @_;
   DX::Action::SetValue->new(
     target_path => $self->target_path,
-    new_value => $value->but_set_action_builder($self)
-                       ->but_set_identity_path($self->target_path)
+    new_value => $self->apply_to_value($value),
   );
 }
 
 sub action_for_add_member {
   my ($self, $at, $value) = @_;
-  my @add_path = (@{$self->target_path}, ref($at) ? $at->string_value : $at);
+  my $ab = $self->specialize_for_member($at);
   DX::Action::AddValue->new(
-    target_path => \@add_path,
-    new_value => $value->but_set_action_builder(
-                   $self->but(target_path => \@add_path)
-                 )->but_set_identity_path(\@add_path)
+    target_path => $ab->target_path,
+    new_value => $ab->apply_to_value($value),
   );
 }
 
 sub action_for_remove_member { die 'WHUT' }
 
+sub apply_to_value {
+  my ($self, $value) = @_;
+  my $new_value = $value->but_set_action_builder($self)
+                        ->but_set_identity_path($self->target_path);
+  return $new_value unless $new_value->isa('DX::Value::Dict');
+  my %m = %{$new_value->members};
+  return $new_value->but(
+    members => {
+      map +($_ => $self->specialize_for_member($_)->apply_to_value($m{$_})),
+        keys %m,
+    },
+  );
+}
+
+sub specialize_for_member {
+  my ($self, $at) = @_;
+  $self->but(
+    target_path => [
+      @{$self->target_path},
+      (ref($at) ? $at->string_value : $at)
+    ],
+  );
+}
+
 1;