############################################################################
##      Copyright (C) 2006 Subredu Manuel  <diablo@iasi.roedu.net>.        #
##                                                                         #
## This program is free software; you can redistribute it and/or modify    #
## it under the terms of the GNU General Public License as published by    #
## the Free Software Foundation; either version 2 of the License, or       #
## (at your option) any later version.                                     #
##                                                                         #
## This program is distributed in the hope that it will be useful,         #
## but WITHOUT ANY WARRANTY; without even the implied warranty of          #
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           #
## GNU General Public License for more details.                            #
##                                                                         #
## You should have received a copy of the GNU General Public License       #
## along with this program; if not, write to the Free Software             #
## Foundation, Inc., 59 Temple Place - Suite 330, Boston,                  #
## MA 02111-1307,USA.                                                      #
############################################################################

package RoPkg::Rsync::Atom;

use strict;
use warnings;

use vars qw($VERSION);

$VERSION = '0.1';

use Scalar::Util qw(blessed);
use English qw( -no_match_vars );

use RoPkg::Exceptions;

sub new {
  my ($class, %opt) = @_;
  my $self;

  $self = bless { %opt }, $class;

  if ( !$self->{'type'} ) {
    Param::Missing->throw('No type specified for this atom');
  }
  else {
    if (
         $self->{type} ne 'comment' && 
         $self->{type} ne 'param'   &&
         $self->{type} ne 'blank'
       ) {
      Param::Wrong->throw('type can be (comment|param|blank)');
    }
  }

  return $self;
}

sub _gs_var {
  my ($self, $pname, $pval) = @_;

  if ( !defined($pval) ) {
    if ( ! exists($self->{$pname}) ) {
      return q{};
    }
    else {
      return $self->{$pname};
    }
  }
  else {
    $self->{$pname} = $pval;
    return $pval;
  }
}

sub Name {
  my ($self, $pval) = @_;

  if ( !blessed($self) ) {
    OutsideClass->throw('Called outside class instance');
  }

  return $self->_gs_var('name', $pval);
}

sub Value {
  my ($self, $pval) = @_;

  if ( !blessed($self) ) {
    OutsideClass->throw('Called outside class instance');
  }

  return $self->_gs_var('value', $pval);
}

sub Type {
  my ($self, $pval) = @_;

  if ( !blessed($self) ) {
    OutsideClass->throw('Called outside class instance');
  }

  return $self->_gs_var('type', $pval);
}

sub ToString {
  my ($self, $ind, $spaces) = @_;
  my $indent;

  if ( !blessed($self) ) {
    OutsideClass->throw('Called outside class instace');
  }

  if ( $self->{type} eq 'blank' ) {
    return $self->{value};
  }

  if ( !defined($spaces) ) {
    $spaces = 0;
  }

  if ( !defined($ind) ) {
    $ind = 1;
    $indent = "\t";
  }
  else {
    if ( $ind ) {
      $indent = "\t";
    }
    else {
      $indent = q{};
    }
  }

  if ( $self->{type} eq 'comment' ) {
    return sprintf("%s%s",
             $indent,
             $self->{value},
           );
  }
  else {
    return sprintf("%s%s%s = %s",
             $indent,
             $self->{name},
             q{ } x ($spaces - length($self->{name})),
             $self->{value},
           );
  }
}

1;

__END__

=head1 NAME

RoPkg::Rsync::Atom - the smallest unit in a rsync configuration file

=head1 SYPONSIS

 #!/usr/bin/perl
 
 use strict;
 use warnings;

 use RoPkg::Rsync::Atom;

 sub main {
   my $a = new RoPkg::Rsync::Atom(
                 type  => 'param',
                 name  => 'uid',
                 value => 'nobody',
               );

   print $a->ToString(0),$/;

   return 0;
 }

 main();

=head1 DESCRIPTION

RoPkg::Rsync::Atom is a class used by RoPkg::Rsync modules. The Atom is considered
the smallest part of any rsync configuration file. An atom can be (at this moment):

=over 3

=item param

=item blank

=item comment

=back

=head1 METHODS

All methods, throw the OutsideClass exception, if you use
them as class methods.
 
B<Example>:
 
 perl -MRoPkg::Rsync::Atom -e 'RoPkg::Rsync::Atom->Type;'
 Called outside class instance

Besides I<OutsideClass> the methods are throwing other exceptions
as well. Refer to each method documentation for more information.

=head2 new()

The constructor of the class. B<new> accepts 3 parameters grouped
inside a hash:

=over 3

=item *) type - type of the atom

=item *) name - name of the atom

=item *) value - value of the atom

=back

The B<type> parameter must always be present. If the B<type> parameter
is not present, a I<Param::Missing> exception is raised.
At this moment, the atoms have 3 types:

=over 3

=item *) param - a parameter in the standard form (name = value)

=item *) comment - a comment

=item *) blank - a blank line (or only with separators)

=back

If the value of the B<type> parameter is not one of the ones
specified a I<Param::Wrong> exception is raised.

=head3 Examples:

B<example 1 (param)>:

 my $a = new RoPkg::Rsync::Atom(
               type  => 'param',
               name  => 'gid',
               value => 'users',
             );

B<example 2 (param)>:

 my $a = new RoPkg::Rsync::Atom(type => 'param');
 $a->Name('gid');
 $a->Value('users');
 print 'Name of the atom is:',$a->Name,$/;

B<example 3 (comment)>:

 my $a = new RoPkg::Rsync::Atom(
               type  => 'comment',
               value => '# this is the group id',
             );

B<example 4 (blank)>:

 my $a = new RoPkg::Rsync::Atom(
               type  => 'blank',
               value => q{ },
             );

=head2 Name($new_name)

The B<Name> method is a get/set method. If I<$new_name>
exists (and his value is defined) then the set behaviour
is selected, otherwise the method acts as a get method.
Returns the name of the atom.

=head2 Value($new_value)

The B<Value> method is a get/set method. If I<$new_value>
exists (and his value is defined) then the set behaviour
is selected, otherwise the method acts as a get method.
Returns the value of the atom.

=head2 ToString($indent, $spaces)

Returns the string representation of the atom. Accepts
2 parameters: I<indent> and I<spaces>.
B<$indent> is a true/false value specifing that the
string representation should be prefixed with
a tab character; B<$spaces> is used to compute
the number of spaces that should be added after
the atom name, so that the total length of the
parameter name to match the I<$spaces> value.

B<Example>:

 my $a = new RoPkg::Rsync::Atom(
               type  => 'param',
               name  => 'gid',
               value => 'users',
             );

 print $a->ToString(0, 6),$/,
       $a->ToString(0, 5),$/,
       $a->ToString(0, 4),$/,
       $a->ToString(0, 3),$/,
       $a->ToString(1, 6),$/,
       $a->ToString(1, 5),$/,
       $a->ToString(1, 4),$/,
       $a->ToString(1, 3),$/;

The result is:
 gid    = users
 gid   = users
 gid  = users
 gid = users
        gid    = users
        gid   = users
        gid  = users
        gid = users


=head2 Type

Returns the type (string representation) of the atom.

=head1 PREREQUISITES

perl 5.008 (or later) is required. Besides perl, you must have the following:

=over 3

=item RoPkg::Exceptions

=item English

=item Scalar::Util

=back

=head1 SEE ALSO

L<RoPkg::Rsync::Node> L<RoPkg::Rsync::ConfFile> L<RoPkg::Exceptions>

=head1 AUTHOR

Subredu Manuel <diablo@iasi.roedu.net>

=head1 LICENSE

Copyright (C) 2005 Subredu Manuel.  All Rights Reserved.
This module is free software; you can redistribute it 
and/or modify it under the same terms as Perl itself.
The LICENSE file contains the full text of the license.

=cut
