NAME
SADI::Simple::Base - Hash-based abstract super-class for all SADI objects
SYNOPSIS
use base qw( SADI::Base );
$self->throw ("This is an error");
DESCRIPTION
This is a hash-based implementation of a general sadi super-class. Most SADI objects should inherit from this.
ACKNOWLEDGEMENTS
Thanks to Martin Senger, the original author of this code, and also to Edward Kawas who refactored it into it's current form.
ACCESSIBLE ATTRIBUTES
Most of the SADI objects are just containers of other objects (attributes, members). Therefore, in order to crete a new SADI object it is often enough to inherit from this SADI::Base
and to list allowed attributes. The object lists only new, additional, attributes (those defined in its parent classes are already available).
This is done by creating a closure with a list of allowed attribute names. These names correspond with the allowed get and set methods. For example:
{
my %_allowed =
(
id => undef,
namespace => undef,
);
}
The closure above allows to call:
$obj->id; # a get method
$obj->id ('my id'); # a set method
$obj->namespace; # a get method
$obj->namespace ('my ns'); # a set method
Well, not yet. The closure also needs two methods that access these (and only these - that is why it is a closure, after all) attributes. Here they are:
{
my %_allowed =
(
id => undef,
namespace => undef,
);
sub _accessible {
my ($self, $attr) = @_;
exists $_allowed{$attr} or $self->SUPER::_accessible ($attr);
}
sub _attr_prop {
my ($self, $attr_name, $prop_name) = @_;
my $attr = $_allowed {$attr_name};
return ref ($attr) ? $attr->{$prop_name} : $attr if $attr;
return $self->SUPER::_attr_prop ($attr_name, $prop_name);
}
}
More about these methods in a moment.
Each attribute has also associated some properties (that is why we need the second method in the closure, the _attr_prop
). For example:
{
my %_allowed =
(
id => undef,
namespace => undef,
date => {type => SADI::Base->DATETIME},
numbers => {type => SADI::Base->INTEGER, is_array => 1},
primitive => {type => SADI::Base->BOOLEAN},
);
...
}
The recognized property names are:
- type
-
It defines a type of its attribute. It can be a primitive type - one of those defined as constants in
SADI::Base
(e.g. "SADI::Base->INTEGER") - or a name of a real object (e.g.SADI::RDF::Core
).When an attribute new value is being set it is checked against this type, and an exception is thrown if the value does not comply with the type.
Default type (used also when the whole properties are undef) is "SADI::Base->STRING".
- is_array
-
A boolean property. If set to true it allows to set more values to this attribute. It also allows to call a method prefixed with
add_
to add a new value (or values) to this attribute.Default value is
false
.Recognized values for
true
are:1
,yes
,true
,+
andano
. Anything else is consideredfalse
. - readonly
-
A boolean property. If set to true the atribute can only be read.
- post
-
A property containing a reference to a subroutine. This subroutine is called after a new value was set. It allows to do some post-processing. For example:
{ my %_allowed = ( value => {post => sub { shift->{isValueCDATA} = 0; } }, ); ... }
Now we know what attribute properties are - so we can define what these methods in closure do (even though you do not need to know - unless The Law of Leaky Abstractions
starts showing).
_accessible ($attr_name)
-
Return 1 if the parameter
$attr_name
is an allowed name to be set/get in this class; otherwise, pass it to the parent class. _attr_prop ($attr_name, $prop_name)
-
Return a value of a property given by name $prop_name for given attribute $attr_name; if such attribute does not exist here, pass it to the parent class.
THROWING EXCEPTIONS
One of the functionalities that SADI::Base
provides is the ability to throw() exceptions with pretty stack traces.
throw
Throw an exception. An argument is an error message.
format_stack
Return a nicely formatted stack trace. The resul includes also an error message given as a scalar argument. Usually, this method is not called directly but via throw
(unless enable_throw_with_stack
was set to true).
print $self->format_stack ("Something terrible happen.");
OTHER SUBROUTINES
new
Create an empty hash-based object. Then call init() in order to do any initializing steps. This class provides only an empty init()
but sub-classes may have it richer. Finally, fill the new object with the given arguments (name/value pairs). The filling is done via set
methods - which means that only attributes allowed for this particular object can be used.
Arguments are name/value pairs. A special case is allowed: when a single element argument occurs, it is treated as a "value". For example, it is allowed to write:
$sadiint = new SADI::Data::Integer (42);
instead of a long way (doing the same):
$sadiint = new SADI::Data::Integer (value => 42);
init
Called after an object has been created (in new()) and before the values given in the constructor have been set. No arguments.
If your sub-class implements this method, make sure that it calls also the same method of its super class:
sub init {
my ($self) = shift;
$self->SUPER::init();
# ... here do what you wish to do
# ...
}
toString
Return an (almost) human-readable description of any object.
Without any parameter, it stringifies the caller object (self). Otherwise it stringifies the object given as parameter.
print $self->toString;
my $good_stuff = { yes => [1,2,3],
no => { net => 'R', nikoliv => 'C' },
};
print $self->toString ($good_stuff);