NAME
    Data::HashArray - An array class of hashes that has magical properties
    via overloading and AUTOLOAD.

ISA
    This class does not descend from any other class.

SYNOPSIS
      my $a = Data::HashArray->new(
                                              {code=>'FR', name=>'France', size=>'medium'},
                                              {code=>'TR', name=>'Turkey', size=>'medium'},
                                              {code=>'US', name=>'United States', size=>'large'}
                                              );

      print $a->[2]->{name};    # Prints 'United States'. No surprise.
      print $a->[0]->{name};    # Prints 'France'. No surprise.
      print $a->{name};             # Prints 'France'. OVERLOADED hash access.

      my $h = $a->hash('code');             # One level hash (returns a hash of a HashArray of hashes)
      my $h = $a->hash('size', 'code');     # Two level hash (returns a hash of a hash of a HashArray  of hashes)

      my $h = $a->hash('size')                                              # One level hash on 'size'.  
      my $h = $a->hash(sub { shift->{'size'}; })    # Same as above, but with a CODE reference

DESCRIPTION
    Normally, Data::HashArray is an array of hashes or hash-based objects.
    This class has some magical properties that make it easier to deal with
    multiplicity.

    First, there exist two overloads. One for hash access and the other for
    stringification. Both will act on the first element of the array. In
    other words, performing a hash access on an object of this class will be
    equivalent to performing a hash access on the first element of the
    array.

    Second, the AUTOLOAD method will delegate any method unkown to this
    class to the first item in the array as well. For this to work, at least
    the first item of the array better be an object on which one could call
    such a method.

    Both of these magical properties make it easier to deal with
    unpredictable multiplicity. You can both treat the object as an array or
    as hash (the first one in the array). This way, if your code deosn't
    know that an element can occur multiple times (in other words, if the
    code treats the element as singular), the same code should still largely
    work when the singualr element is replaced by a Data::HashArray object.

    The other practical feature of this class is the capabality to place the
    objects (or hashes) in the array into a hash keyed on the value of a
    given field or fields (see the "hash()" method for further details).

OVERLOADS
    Two overloads are performed so that a Data::HashArray object looks like
    a simple hash or a singular object if treated like one.

   hash access
    If an object of this class is accessed as if it were a reference to a
    hash with the usual "$object->{$key}" syntax, it will *behave* just like
    a genuine hash. The access will be made on the first item of the array
    (as this is an array class) assuming this item is a hash or hash-based
    object.

   stringification
    If an object of this class is accessed as if it were a string, then the
    stringification of the first item of the array will be returned.

METHODS
  CONSTRUCTORS
   new()
      my $array = Data::HashArray->new();           # An empty array
      my $array = Data::HashArray->new(@items);     # An array with initial items in it.

    CONSTRUCTOR.

    The new() constructor method instantiates a new Data::HashArray object.
    This method is inheritable.

    Any items that are passed in the parameter list will form the initial
    items of the array.

  OTHER METHODS
   hash()
      my $h = $array->hash($field);         # Single hash level with one key field
      my $h = $array->hash(@fields);        # Multiple hash levels with several key fields
      
  my $h = $array->hash('size')                                          # Concrete example. Hash on 'size'.  
      my $h = $array->hash(sub { shift->{'size'}; })        # Same as above, but with a CODE reference

    OBJECT METHOD.

    Remember that the items of a Data::HashArray object are supposed to be
    hashes or at least hash-based objects.

    When called with a single argument, the hash() method will create a hash
    of the items of the array keyed on the value of the argument 'field'.

    An example is best. Assume that we have a Data::HashArray object that
    looks like the following :

      my $array = bless ([
                          {code=>'FR', name=>'France', size=>'medium'},
                          {code=>'TR', name=>'Turkey', size=>'medium'},
                          {code=>'US', name=>'United States', size=>'large'}
                         ], 'Data::HashArray');

    Now, if we make a call to hash() as follows:

      my $hash = $array->hash('code');

    Then the resulting hash will look like the following:

      $hash = {
               FR=> bless ([{code=>'FR', name=>'France', size=>'medium'], 'Data::HashArray'),
               TR=> bless ([{code=>'TR', name=>'Turkey', size=>'medium'], 'Data::HashArray'),
               US=> bless ([{code=>'US', name=>'United States', size=>'large'}, 'Data::HashArray')
      };

    When, multiple fields are passes, then multiple levels of hashes will be
    created each keyed on the field of the corresponding level.

    If, for example, we had done the following call on the above array: my
    $hash = $array->hash('size', 'code'};

    We would then get the following hash:

      $hash = {
            large =>  {
                    US=> bless ([{code=>'US', name=>'United States', size=>'large'}, 'Data::HashArray')
                    },
            medium => {
                     FR=> bless ([{code=>'FR', name=>'France', size=>'medium'}], 'Data::HashArray'),
                     TR=> bless ([{code=>'TR', name=>'Turkey', size=>'medium'}], 'Data::HashArrayy')
                     }
       };

    Note that the last level of the hierarachy is always a HashArray of
    hashes. This is done to accomodate the case where more then one item can
    have the same key.

    Note that the arguments to this method could also be CODE references. In
    that case, the CODE is executed for each item in the array, passing the
    item reference as the first argument to the CODE refernce. The code
    BLOCK should return the expected key value for the item.

    For example, the following are equivalent:

      my $h = $array->hash('size')                                          # Concrete example. Hash on 'size'.  
      my $h = $array->hash(sub { shift->{'size'}; })        # Same as above, but with a CODE reference passed as an argument.

    .

BUGS & CAVEATS
    There no known bugs at this time, but this doesn't mean there are aren't
    any. Use it at your own risk.

    Note that there may be other bugs or limitations that the author is not
    aware of.

AUTHOR
    Ayhan Ulusoy <dev@ulusoy.name>

COPYRIGHT
      Copyright (C) 2006-2008 Ayhan Ulusoy. All Rights Reserved.

    This module is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

DISCLAIMER
    BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
    FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
    PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
    EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
    ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
    YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
    NECESSARY SERVICING, REPAIR, OR CORRECTION.

    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
    REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE
    TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR
    CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
    SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
    RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
    FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
    SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    DAMAGES.

