Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

URI Inheritence

by gdearing (Novice)
on Nov 12, 2004 at 22:02 UTC ( [id://407543]=perlquestion: print w/replies, xml ) Need Help??

gdearing has asked for the wisdom of the Perl Monks concerning the following question:

Hi.

I’m updating (and trying to clean) a legacy perl app that deals with document management. It seems that it has been repeatedly patched through the years, with various developers tacking on functionality. It’s now large, sprawling piece of code with lots of secondary programs tapping into its libraries.

It uses URI::URL throughout. This would be fine, despite being deprecated, except that the system utilizes numerous secondary hashes to store “extra” information about the URI. A common example…

my $uri = new URI::URL “http://foo.bar”; $self->{URL}->{$uri}->{authenticated} = 1; $self->{URL}->{$uri}->{available} = 1; … return $uri;

The rest of the code calls back into the creating object to “lookup” the extra URI information and the creating object isn’t even in scope in some areas.

My original plan was to create a new class which inherited from the URI class via an @ISA relationship. This would let me bundle the extra data with the URI, while ensuring backward compatibility throughout the applications. As many of you probably already know, I ran into a few snags…here are the big ones:

  • URI and URL::URI objects rely on being usable as ‘rvalues’. The URI is a scalar and the URL::URI is an array with a single element.

  • URI morphs itself into new classes during construction, such as URI::http. If you make an @ISA subclass, your object will morph when the URI constructor is called. This might be managed via multiple/dynamic inheritance, but is messy.
I suspect I’m going to end up creating a new class that ‘contains’ a URI and create pass-through methods that transfer calls from my new class to the contained class. The problems with this are…

  • The pass-through methods are unlikely to be updated regularly… is there an automagical way to maintain these safely?

  • Many programs out there already rely on being able to use a URI::URL object as a scalar… ie. 'print if $uri =~ /pdf\s+$/;’ Is there any way to control the value returned when an object is used in a scalar context?

Thanks in advance for any suggestions. If I can’t maintain the rvalue functionality, it’ll be a lot of work just to find all the programs with dependencies on these libraries, much less updating and testing them.

Replies are listed 'Best First'.
Re: URI Inheritence
by Tuppence (Pilgrim) on Nov 12, 2004 at 22:49 UTC

    While I have nothing to offer for the rest of your post,

    The pass-through methods are unlikely to be updated regularly… is there an automagical way to maintain these safely?

    I can answer: Yes. Class::MethodMaker supports creating forward methods. This makes your methods for forwarding be one line in a use Class::MethodMaker scenario, as in

    use Class::MethodMaker get_set => [ qw/uri/], forward => [ uri => [qw/param field validate/]] +;

    where param field and validate are all forwarded methods that you want.

    Hope this helps

Re: URI Inheritence
by fglock (Vicar) on Nov 13, 2004 at 01:33 UTC

    Many programs out there already rely on being able to use a URI::URL object as a scalar… ie. 'print if $uri =~ /pdf\s+$/;’ Is there any way to control the value returned when an object is used in a scalar context?

    You can overload the "" (stringification) operation:

    package Pkg; use overload '""' => sub { "[[[" . $_[0]->{val} . "]]]" }; package Main; my $x = { val => '10' }; bless $x, Pkg; print $x; # [[[10]]]
Re: URI Inheritence
by steves (Curate) on Nov 12, 2004 at 22:48 UTC

    You should be able to use AUTOLOAD to implement method pass-through. I've done this in similar contexts. You basically build the AUTOLOAD method in your new class to say, "If the URI::URL object I contain has the method being called, then call it. Otherwise raise an exception."

    For the scalar context issue, I believe that URI::URL overloads the "stringify" operator using operator overloading. Your new class could do the same thing if that's the case.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://407543]
Approved by Arunbear
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (2)
As of 2024-04-24 04:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found