NAME

Class::Rebless - Rebase namespaces, hierarchically

SYNOPSIS

use Class::Rebless;

my $beat = bless({
  one => bless({
    hey => 'ho',
  }, 'AOne'),
  two => bless({
    list => [
      bless({ three => 3 }, 'AThree'),
      bless({ four  => 4 }, 'AFour'),
      5,
      "this is just noise",
    ],
  }, 'ATwo'),
  six => {
    seven => bless({ __VALUE__ => 7}, 'ASeven'),
    eight => bless({ __VALUE__ => 8}, 'AnEight'),
  },
}, 'AOne');

Class::Rebless->rebase($beat, 'And');

# $beat now contains objects of type
# And::AOne, And::ATwo .. And::AnEight!

Class::Rebless->rebless($beat, 'Beatless');

# All (blessed) objects in $beat now belong to package
# Beatless.

DESCRIPTION

Class::Rebless takes a Perl data structure and recurses through its hierarchy, reblessing objects that it finds along the way into new namespaces. This is typically useful when your object belongs to a package that is too close to the main namespace for your tastes, and you want to rebless everything down to your project's base namespace.

Class::Rebless walks scalar, array, and hash references. As of this early version it assumes all other non-builtin references are objects with fields implemented as hashrefs and attempts to walk them as such. This limitation will be addressed in future versions.

Methods

Class::Rebless defines only class methods. There is no instance constructor, and when calling these methods you should take care not to call them in function form by mistake; that would not do at all.

rebless
Class::Rebless->rebless($myobj, "New::Namespace");

Finds all blessed objects refered to by $myobj and reblesses them into New::Namespace. This completely overrides whatever blessing they had before.

rebase
Class::Rebless->rebase($myobj, "New::Namespace::Root");

Finds all blessed objects refered to by $myobj and reblesses them into new namespaces relative to New::Namespace::Root. This overrides whatever blessing they had before, but unlike rebless, it preseves something of the original name. So if you had an object blessed into "MyClass", it will now be blessed into "New::Namespace::Root::MyClass".

custom
Class::Rebless->custom($myobj, "MyName", { editor => \&my_editor });

Per each visited object referenced in $myobj, calls my_editor() on it. The editor routine is passed the current object in the recursion and the wanted namespace ("MyName" in the code above). This lets you to do anything you like with each object, but is (at least nominally) intended to allow filtering out objects you don't want to rebless. 3rd party objetcs, for example:

my $fh      = IO::File->new("data") or die "open:$!";
my $frobber = Frotz->new({ source => $fh });
Class::Rebless->custom($frobber, "SuperFrotz", { editor => \&noio });

sub noio {
    my($obj, $namespace) = @_;
    return if ref($obj) =~ /^IO::/;

    bless $obj, $namespace . '::' . ref $obj;
}

(A more realistic example might actually use an inclusion filter, not an inclusion filter.)

CAVEATS

As mentioned above, the present version assumes any objects it encounters along the recursion are blessed hashrefs. This will lead to disaster if a reblessing is attempted on less typical objects.

TODO

Figure out a way to detect object type.

Add a "prune" feature, most likely by specifying a magic return value for custom rebless editors.

Make a proper test suite (currently a rudimentary unit test is available by running "perl Class/Rebless.pm")

AUTHOR

Gaal Yahas <gaal@forum2.org>

Copyright (c) 2004 Gaal Yahas. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.