#!/usr/bin/perl -w

#############################################################################
# Item - a simple object
#
# Copyright (C) 1999-2000 by Tels. All rights reserved.
#############################################################################

package CoW::Item;
use vars qw($VERSION);
$VERSION = 1.00;    # Current version of this package
require  5.005;     # requires this Perl version or later

use base Exporter;
@EXPORT_OK	= qw( );
@EXPORT		= qw( );
use strict;
use vars qw($AUTOLOAD);

sub new
  {
  # create a new data thingy (with named parameters)
  my $class = shift;
  $class = ref($class) || $class;
  #print "$class\n";
  my $args;
  if (!defined $_[0])   # ()
    {
    $args = {};
    }
  else
    {
    $args = ref($_[0]) ? $_[0] : { @_ }; # ( reftohash ) or ( array )
    }
  my $self = {};
  bless $self, $class;
  $self->_init($args);
  return $self;
  }
   
#############################################################################
# private, initialize self 

sub _init
  {
  my $self = shift;
  my $args = shift;
  
  # simple make copy
  foreach my $k (keys %$args)
    {
    die "Can't set private $k in $self." if $k =~ /^_/;
    $self->{$k} = $args->{$k};
    } 
  die ('$self can not contain other things.') if exists $self->{contains};
  return $self;
  }

sub _default
  {
  # check wether the given args exist and are defined, if not, set
  # defaults
  my $self = shift;
  my $args = shift;
  foreach my $k (keys %$args)
    {
    die "Can't require private $k in $self." if $k =~ /^_/;
    $self->{$k} = $args->{$k} if (!defined $self->{$k});
    }
  return $self;
  }

#############################################################################
# public stuff

sub as_string
  {
  my $self = shift;
  # print yourself as text
  # if a scalar reference is given, add yourself to this
  my $t = shift;
  #print "$self $t\n";
  if (!defined $t) { my $c = ""; $t = \$c; }
  my $level = shift || 0;
  my $a; my $space = " " x $level;
  $$t .= "$space".ref ($self)." {\n";
  foreach my $f (sort keys %$self)
    {
    next if $f =~ /^_/;               # skip internals
    if (ref($self->{$f}))
      {
      $a = ''; $self->{$f}->as_string(\$a,$level+2); $a =~ s/^\s+//;    
      }
    else
      {
      $a = $self->{$f}; $a = "\"$a\"" unless $a =~ /^[a-z0-9_.]+$/;
      $a .= "\n";
      }
    $$t .= "$space  $f = $a";
    }
  $$t .= "$space}\n";
  return $$t;
  }

sub copy
  {
  # make a copy of yourself
  my $self = shift;

  my $class = ref($self);
  my $new = $class->new();
  foreach (keys %$self)
    {
    next if /^_/;               # skip internals
    $new->{$_} = $self->{$_};   # make copy of public fields
    }
  return $new;
  }
 
1; 

__END__

#############################################################################

=pod

=head1 NAME

Item - a simple object/thingie.

=head1 SYNOPSIS

	use Item;

	my $item = new Item ( name => 'item', foo => 9 );

	$item->_default (foo => 8, blah => 8);	# will set only blah, since
						# foo is already set
	print $item->{name},"\n";

=head1 REQUIRES

perl5.005, Exporter

=head1 EXPORTS

Exports nothing.

=head1 DESCRIPTION

Item offers a C<new()> method which provides I<named parameters>, and
an C<_init()> method, which you can override to do any initialisation your
object needs.

An B<Item> can NOT contain other things, use a L<Bunch|Bunch> instead.

=head1 FIELDS

Defines no private or public fields.

=head1 METHODS

=head2 new

Create a new item. No need to override it. See L<_init|_init> instead.

=head2 copy

Make a copy of this Item, minus the private fields.

=head2 _init

Init the item, automatically called by C<new()>. 
Takes a reference to a hash, and copies all keys found
in that hash to itself. Will C<die> if you try to set a private field (fields
that start with "_") or the for L<Bunches|Bunch> reserved field "contains".
If your derived object want's to do some post-init, or pre-init, use the
following:

	sub _init
	  {
          my $self = shift;
	  my $args = shift;

	  # your pre-init here
	  $self->SUPER::_init($args);	# use parent init
	  # your post-init here
	  }

=head2 _default

Set default values for uninitialized/undef fields. Takes a reference to a hash
and for each key, will check wether the field with that name is undefined. If
found undefined, will set the value from the hash for this field.

=head1 BUGS

None known yet.

=head1 AUTHOR

Tels http://bloodgate.com in late 2000.

=cut

