[%# A template for an datatype property.
    ===========================
    Expected/recognized parameters:
    obj ... a SADI::Data::Def::OWLClass object
      
-%]
#-----------------------------------------------------------------
# [% obj.module_name %]
# Generated: [% USE Date (format = '%d-%b-%Y %H:%M:%S %Z') %][% Date.format %]
# Contact: Edward Kawas <edward.kawas+sadi@gmail.com>
#-----------------------------------------------------------------
package [% obj.module_name %];

#use SADI::Base;

[% FOREACH child IN obj.module_parent -%]
use [% child %];
[% END %]

no strict;
use vars qw( @ISA );
@ISA = qw(
 [% obj.module_parent.join("\n ") %] 
);
use strict;

# imports 
use SADI::Data::String;
use SADI::Data::Integer;
use SADI::Data::Float;
use SADI::Data::Boolean;
use SADI::Data::DateTime;

[% FOREACH child IN obj.object_properties -%]
use [% child.module_name %];[% END %]
[% FOREACH child IN obj.datatype_properties -%]
use [% child.module_name %];[% END %]

{
    my %_allowed = (
    [% FOREACH child IN obj.object_properties %]
        [% child.name %] => {
        	type => 'SADI::Data::OWL::Class',
        	# range checking of classes added 
        	post => sub {
        		my ($self) = shift;
                my $type = @{$self->[% child.name %]}[-1];
                return unless defined $type and $type->type;
                my $range = new [% child.module_name %]->range();
                return unless $range;
                $range = $self->uri2package($range);
                eval {
                	$range = $range->new();
                };
                return if $@;
        		$self->throw("\n" . $type->type() . "\nis not related to\n" . $range->type()) unless $type->isa(ref($range));
        	},
        	is_array => 1, },
    [% END %]
    [% FOREACH child IN obj.datatype_properties %]
        [% child.name %] => {
            type => '[% child.module_name %]',
            is_array => 1, },
    [% END %]
    );

    sub _accessible {
        my ( $self, $attr ) = @_;
        exists $_allowed{$attr} 
[% FOREACH child IN obj.module_parent -%]
          or $self->[%- child -%]::_accessible($attr)
[% END -%]
    }

    sub _attr_prop {
        my ( $self, $attr_name, $prop_name ) = @_;
        my $attr = $_allowed{$attr_name};
        return ref($attr) ? $attr->{$prop_name} : $attr if $attr;
[% FOREACH child IN obj.module_parent -%]
        return $self->[%- child -%]::_attr_prop( $attr_name, $prop_name ) 
            if $self->[%- child -%]::_accessible($attr_name);
[% END %]
    }
}

#-----------------------------------------------------------------
# init
#-----------------------------------------------------------------
sub init {
    my ($self) = shift;
[% FOREACH child IN obj.module_parent -%]
    $self->[%- child -%]::init();
[% END -%]
    $self->type('[% obj.type %]');
    
}

# every generated module implements this ...
sub _get_statements {
    my $self = shift;
    # create a named resource or bnode for this object ....
    my $subject = new RDF::Core::Resource( $self->value ) if defined $self->value and $self->value ne '';
    $subject = new RDF::Core::NodeFactory()->newResource unless defined $self->value and $self->value ne '';
    # set the subject so that this sub graph can be linked to other graphs
    $self->subject($subject);
    my $predicate = $subject->new( SADI::RDF::Predicates::RDF->type );
    my $object = new RDF::Core::Resource( $self->type );
    
    $self->add_statements(new RDF::Core::Statement($subject, $predicate, $object));
    
    # for each attribute, if is array do:
[% FOREACH child IN obj.object_properties -%]
    foreach (@{$self->[%- child.name -%]}) {
        # add all statements from $_
        $self->add_statements($_->_get_statements) if $_->_get_statements;
        # add a statement linking the graphs
        $self->add_statements(
          new RDF::Core::Statement(
              $subject,
              $subject->new('[%- child.uri -%]'), 
              $_->subject
          )
        );
    }
[% END -%]
[% FOREACH child IN obj.datatype_properties -%]
    foreach (@{$self->[%- child.name -%]}) {
        $self->add_statements(
          new RDF::Core::Statement(
              $subject,
              $subject->new('[%- child.uri -%]'), 
              new RDF::Core::Literal( 
                $_->value, undef, (defined $_->range ? $_->range : undef) 
              ),
          )
        );
    }
[% END -%]
    # add parent statements too
[% FOREACH child IN obj.module_parent -%]
    eval {$self->add_statements($self->[%- child -%]::_get_statements());};
[% END %];
    return $self->statements;
}

1;

__END__

=head1 NAME

[% obj.module_name %] - an owl class generated by SADISeS for SADISeS!

=head1 SYNOPSIS

  use [% obj.module_name %];
  my $class = [% obj.module_name %]->new();

  # get the uri for this class
  my $uri = $property->uri;

[% IF obj.datatype_properties -%]
  # add datatype properties 
[% FOREACH child IN obj.datatype_properties -%]
  use [% child.module_name %];
  my $[% child.name %] = new [% child.module_name %]('some value');
  $class->add_[% child.name %]($[% child.name %]);
  # get the [% child.name %] datatype properties
  $class->[% child.name %];
[% END %][% END %]
  
[% IF obj.object_properties -%]
  # add object properties 
[% FOREACH child IN obj.object_properties -%]
  use [% child.module_name; %]
  my $[% child.name %] = new [% child.module_name %]('');
  $class->add_[% child.name %]($[% child.name %]);
  # get the [% child.name %] object properties
  $class->[% child.name %];
[% END %][% END %]

=head1 DESCRIPTION

I<Inherits from>:
[% FOREACH child IN obj.module_parent -%]
L<[% child %]>
[% END %]

=cut

