This is a follow-up to my April 4th message where I requested the 
namespace for File::VirtualPath.  At that time my description may 
have seemed vague since I didn't actually have a module to show you.

Now I have uploaded my documented File::VirtualPath module to my web 
server, where you can see it at 
"http://www.darrenduncan.net/perl/HTML-Application-0.4/VirtualPath.pm". 
You can look there to see exactly what I am talking about when I say 
I want to register it.  It should be on CPAN in a few days.

Here is the module's DLSI:

Name              DSLI Description                                  Info
------------      ---- -------------------------------------------- ----
File::
::VirtualPath     bdpO Portable abstraction of a file/dir/url path  DUNCAND

At the end of this letter I have copied part of the module's POD, to 
save you having to look elsewhere if you don't need to.

I believe that this module is unique and there are not others like it 
on CPAN.  Any CPAN modules that may look similar at first, such as 
"File::Path", aren't because the others actually talk to the 
filesystem to get things done and my module is just a 
translation-type data structure.

If you have any questions then please ask.  Or if you have 
suggestions for a more appropriate name then I can hear it (but I did 
do my research).

Thank you,

// Darren Duncan

----------------------------------

NAME

File::VirtualPath - Portable abstraction of a file/dir/url path.

DEPENDENCIES

Perl Version

    5.004

Standard Modules

    I<none>

Nonstandard Modules

    I<none>

SYNOPSIS

Content of thin shell "startup.pl":

    #!/usr/bin/perl
    use strict;

    my $root = "/home/johndoe/projects/aardvark";
    my $separator = "/";
    if( $^O =~ /Win/i ) {
       $root = "c:\\projects\\aardvark";
       $separator = "\\";
    }
    if( $^O =~ /Mac/i ) {
       $root = "Documents:projects:aardvark";
       $separator = ":";
    }

    use Aardvark;
    Aardvark->main( File::VirtualPath->new( $root, $separator ) );

    1;

Content of fat main program "Aardvark.pm"

    package Aardvark;
    use strict;
    use File::VirtualPath;

    sub main {
       my (undef, $project_dir) = @_;
       my $prefs = &get_prefs( $project_dir->child_path_obj( 'config.pl' ) );
       &do_work( $prefs, $project_dir );
    }

    sub get_prefs {
       my ($project_dir) = @_;
       my $real_filename = $project_dir->physical_path_string();
       my $prefs = do $real_filename;
       defined( $prefs ) or do {
          my $virtual_fn = $project_dir->path_string();
          die "Can't get Aardvark prefs from file '$virtual_fn': $!";
       };
       return( $prefs );
    }

    sub do_work {
       my ($prefs, $project_dir) = @_;
       my ($lbl_a, $lbl_b, $lbl_c) = ($prefs->{a}, $prefs->{b}, $prefs->{c});
       my $data_source = $prefs->{'sourcefile'};
       open( SOURCE, $project_dir->child_path_string( $data_source ) );
       while( my $line = <SOURCE> ) {
          my ($a, $b, $c) = split( "\t", $line );
          print "File contains: $lbl_a='$a', $lbl_b='$b', $lbl_c='$c'\n";
       }
       close( SOURCE );
    }

    1;

Content of settings file "config.pl"

    $rh_prefs = {
       sourcefile => 'mydata.txt',
       a => 'name',
       b => 'phone',
       c => 'date',
    };

DESCRIPTION

This Perl 5 object class implements a portable abstraction of a 
resource path, examples of which include file-system paths like 
"/usr/bin/perl" and URLs like "http://www.cpan.org/modules/".  It is 
designed to support applications that are easily portable across 
systems because common platform-specific details are abstracted away. 
Abstracted details include the location of your project within the 
file-system and the path separator for your OS; you can write your 
application as if it is in the root directory of a UNIX system, and 
it will function correctly when moved to any subdirectory or to a Mac 
or Windows system.

OVERVIEW

This class is implemented as a simple data structure which stores an 
array of path segments such as ['', 'usr', 'bin', 'perl'] in a 
virtual file-system. The majority part of your application works with 
these objects and passes them around during its routines of locating 
config or data or other files.

As your application navigates the virtual file-system, it uses object 
methods like chdir() to tell the object where the app thinks it is 
now.  When your program actually needs to use files, it asks a method 
like physical_path_string() to give it a string representing the 
current path in the real world, which it then passes to your standard 
I/O functions like open().

For example, the program may think it is sitting in "/config/access", 
but it actually makes an open call to 
"/home/johndoe/projects/aardvark/config/access". If you move the 
"aardvark" project to a Windows system, the real path may have 
changed to "c:\projects\aardvark\config\access", but your program 
would never need to know the difference (aside from any internal file 
format issues).

In order for this to work, a small part of your program needs to know 
the truth of where the project it is working on is located.  But that 
part can be a very lightweight shim which initializes a single 
File::VirtualPath object and then passes it to the fat portable part 
of the program.  There are two bits of data that your shim needs to 
provide: 1. A string having the full real-world path of your project 
root directory; 2. A string having the real-world path separator. See 
the SYNOPSIS for an example.

Then, your main program just needs to assume that the argument it was 
passed is currently in the virtual root directory and go from there.

    THIN CONFIG SHELL <----> File::VirtualPath <----> FAT PROGRAM CORE
    (may be portable)        (portable)               (portable)

Taking this idea further, it is easy for program code to be reused 
for multiple projects, simultaneously, because each would only need a 
different thin shim program which points to a different physical 
directory as the virtual root.

Taking this idea further, File::VirtualPath makes it easier for you 
to separate your application into components that have their own 
files to keep track of. When your main program calls a component, it 
can pass a modified FVP object which that component uses as its own 
virtual root.  And so you can have multiple instances of program 
components each working in different directories, and no logic for 
working this out needs to be in the components themselves.

On a final note, the paths returned by this class are all absolute. 
Therefore you never need to do a real "chdir" or "cd" operation in 
your program, and your executable doesn't have to be located in the 
same place as its data.  This is particularly useful if you are 
calling your program using a link/alias/shortcut.

Reply via email to