3 package MooseX::Clone::Meta::Attribute::Trait::Clone;
8 use namespace::clean -except => 'meta';
10 with qw(MooseX::Clone::Meta::Attribute::Trait::Clone::Base);
12 sub Moose::Meta::Attribute::Custom::Trait::Clone::register_implementation { __PACKAGE__ }
14 has clone_only_objects => (
20 has clone_visitor => (
21 isa => "Data::Visitor",
26 has clone_visitor_config => (
29 default => sub { { } },
32 sub _build_clone_visitor {
35 require Data::Visitor::Callback;
37 Data::Visitor::Callback->new(
38 object => sub { $self->clone_object_value($_[1]) },
40 %{ $self->clone_visitor_config },
45 my ( $self, $target, $proto, @args ) = @_;
47 if ( $self->has_value($proto) ) {
48 my $clone = $self->clone_value_data( scalar($self->get_value($proto)), @args );
50 $self->set_value( $target, $clone );
54 if ( exists $args{init_arg} ) {
55 $self->set_value( $target, $args{init_arg} );
60 sub clone_value_data {
61 my ( $self, $value, @args ) = @_;
63 if ( blessed($value) ) {
64 return $self->clone_object_value($value, @args);
68 if ( exists $args{init_arg} ) {
69 return $args{init_arg};
71 unless ( $self->clone_only_objects ) {
72 return $self->clone_any_value($value, @args);
80 sub clone_object_value {
81 my ( $self, $value, %args ) = @_;
83 if ( $value->can("clone") ) {
86 if ( exists $args{init_arg} ) {
87 my $init_arg = $args{init_arg};
89 if ( ref $init_arg ) {
90 if ( ref $init_arg eq 'HASH' ) { @clone_args = %$init_arg }
91 elsif ( ref $init_arg eq 'ARRAY' ) { @clone_args = @$init_arg }
93 croak "Arguments to a sub clone should be given in a hash or array reference";
96 croak "Arguments to a sub clone should be given in a hash or array reference";
100 return $value->clone(@clone_args);
102 croak "Cannot recursively clone a retarded object $value (" . overload::StrVal($value) . ") in " . $args{attr}->name . ". Try something better.";
106 sub clone_any_value {
107 my ( $self, $value, %args ) = @_;
108 $self->clone_visitor->visit($value);
121 MooseX::Clone::Meta::Attribute::Trait::Clone - The L<Moose::Meta::Attribute>
122 trait for deeply cloning attributes.
129 traits => [qw(Clone)],
133 $object->clone; # will recursively call $object->foo->clone and set the value properly
137 This meta attribute trait provides a C<clone_value> method, in the spirit of
138 C<get_value> and C<set_value>. This allows clone methods such as the one in
139 L<MooseX::Clone> to make use of this per-attribute cloning behavior.
143 Deriving this role for your own cloning purposes is encouraged.
145 This will allow your fine grained cloning semantics to interact with
146 L<MooseX::Clone> in the Rightâ„¢ way.
152 =item clone_only_objects
154 Whether or not L<Data::Visitor> should be used to clone arbitrary structures.
155 Objects found in these structures will be cloned using L<clone_object_value>.
157 If true then non object values will be copied over in shallow cloning semantics
160 Defaults to false (all reference will be cloned).
162 =item clone_visitor_config
164 A hash ref used to construct C<clone_visitor>. Defaults to the empty ref.
166 This can be used to alter the cloning behavior for non object values.
170 The L<Data::Visitor::Callback> object that will be used to clone.
172 It has an C<object> handler that delegates to C<clone_object_value> and sets
173 C<tied_as_objects> to true in order to deeply clone tied structures while
176 Only used if C<clone_only_objects> is false and the value of the attribute is
185 =item clone_value $target, $proto, %args
187 Clones the value the attribute encapsulates from C<$proto> into C<$target>.
189 =item clone_value_data $value, %args
191 Does the actual cloning of the value data by delegating to a C<clone> method on
194 If the object does not support a C<clone> method an error is thrown.
196 If the value is not an object then it will not be cloned.
198 In the future support for deep cloning of simple refs will be added too.
200 =item clone_object_value $object, %args
202 This is the actual workhorse of C<clone_value_data>.
204 =item clone_any_value $value, %args
206 Uses C<clone_visitor> to clone all non object values.
208 Called from C<clone_value_data> if the value is not an object and
209 C<clone_only_objects> is false.