#
# Copyright (c) 2005-2006 IBM Corporation.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# File: $Source: /var/lib/cvs/ODO/lib/ODO/Ontology/OWL/Lite/Thing.pm,v $
# Created by: Stephen Evanchik( <a href="mailto:evanchik@us.ibm.com">evanchik@us.ibm.com </a>)
# Created on: 04/27/2005
# Revision: $Id: Thing.pm,v 1.3 2010-02-17 17:17:09 ubuntu Exp $
#
# Contributors:
# IBM Corporation - initial API and implementation
#
package ODO::Ontology::OWL::Lite::Thing;
# Ultimate ancestor class for OWL classes.
use strict;
use warnings;
use Class::ISA;
use ODO::Node;
use ODO::Exception;
use ODO::Query::Simple::Parser;
use ODO::Ontology::RDFS::Vocabulary;
use vars qw /$VERSION/;
$VERSION = sprintf "%d.%02d", q$Revision: 1.3 $ =~ /: (\d+)\.(\d+)/;
use base qw/ODO/;
our @ISA;
our @METHODS = qw/graph subject propertyContainerName properties/;
__PACKAGE__->mk_accessors(@METHODS);
__PACKAGE__->mk_ro_accessors(qw/min_cardinality max_cardinality propertyURIMap/);
sub value {
my $self = shift;
throw ODO::Exception::Runtime(error=> 'Subject is not an ODO::Node object')
unless($self->subject()->isa('ODO::Node'));
return $self->subject()->value();
}
sub isRequiredProperty {
my ($self, $propertyPackageName) = @_;
my $minCardinality = $self->minCardinality($propertyPackageName);
return ($minCardinality) ? 1 : 0;
}
sub minCardinality {
my ($self, $propertyPackageName) = @_;
my $minCardinalityHash = $self->{'min_cardinality'};
if(exists($minCardinalityHash->{$propertyPackageName})) {
return $minCardinalityHash->{$propertyPackageName};
}
return undef;
}
sub setMinCardinality {
my ($self, $propertyPackageName, $value) = @_;
my $minCardinalityHash = $self->{'min_cardinality'};
$minCardinalityHash->{ $propertyPackageName } = $value;
}
sub maxCardinality {
my ($self, $propertyPackageName) = @_;
my $maxCardinalityHash = $self->{'max_cardinality'};
if(exists($maxCardinalityHash->{$propertyPackageName})) {
return $maxCardinalityHash->{$propertyPackageName};
}
return undef;
}
sub setMaxCardinality {
my ($self, $propertyPackageName, $value) = @_;
my $maxCardinalityHash = $self->{'max_cardinality'};
$maxCardinalityHash->{ $propertyPackageName } = $value;
}
sub validateMinCardinality {
my ($self, $propertyPackageName) = @_;
my $minCardinality = $self->minCardinality($propertyPackageName);
return 1 # Trivially validates if owl:minCardinality is not specified
unless(defined($minCardinality));
my $propertyInstances = $self->getPropertyFromGraph($propertyPackageName);
my $numPropertyInstances = scalar(@{ $propertyInstances });
if($minCardinality == 0) {
# Do nothing, it is optional
}
if( $minCardinality == 1
&& $propertyInstances == 0) {
throw ODO::Ontology::Evaluation(error=> "$propertyPackageName: minCardinality is restricted to 1 property, one instance must be present");
}
return $propertyInstances;
}
sub validateMaxCardinality {
my ($self, $propertyPackageName) = @_;
my $maxCardinality = $self->maxCardinality($propertyPackageName);
return 1 # Trivially validates if owl:maxCardinality is not specified
unless(defined($maxCardinality));
my $propertyInstances = $self->getPropertyFromGraph($propertyPackageName);
my $numPropertyInstances = scalar(@{ $propertyInstances });
if( $maxCardinality == 1
&& $numPropertyInstances > 1) {
throw ODO::Ontology::Evaluation(error=> "$propertyPackageName: maxCardinality is restricted to 1 property");
}
if( $maxCardinality == 0
&& $numPropertyInstances > 0) {
throw ODO::Ontology::Evaluation(error=> "$propertyPackageName: maxCardinality is restricted to 0");
}
my $minCardinality = $self->minCardinality($propertyPackageName);
$minCardinality = 0 # If owl:minCardinality isn't specified then make it 0 (optional)
unless(defined($minCardinality));
if( $maxCardinality == 1
&& $maxCardinality == $minCardinality
&& $numPropertyInstances != 1) {
throw ODO::Ontology::Evaluation(error=> "$propertyPackageName: Property must exist exactly once");
}
if( $maxCardinality == 0
&& $maxCardinality == $minCardinality
&& $numPropertyInstances > 0) {
throw ODO::Ontology::Evaluation(error=> "$propertyPackageName: Property can not exist");
}
return $propertyInstances;
}
sub canAddProperty {
my ($self, $propertyPackageName) = @_;
my $propertyInstances = $self->getPropertyFromGraph($propertyPackageName);
my $numPropertyInstances = scalar(@{ $propertyInstances });
my $minCardinality = $self->minCardinality($propertyPackageName);
$minCardinality = 0
unless(defined($minCardinality));
my $maxCardinality = $self->maxCardinality($propertyPackageName);
if( defined($maxCardinality)
&& $numPropertyInstances + 1 > $maxCardinality) {
return 0;
}
elsif($numPropertyInstances + 1 >= $minCardinality) {
return 1;
}
else {
# FIXME: Add more conditionals here?
}
}
sub isOfType {
my ($self, $classPackageName) = @_;
return 1
if(UNIVERSAL::isa($self, $classPackageName));
my $myURI = $self->subject()->value();
my $rdfType = $ODO::Ontology::RDFS::Vocabulary::type;
my $uri = $classPackageName->objectURI();
my $typeQuery = "SELECT ?stmt WHERE (<$myURI>, <$rdfType>, <$uri>)";
my $results = $self->issueQuery($typeQuery);
return (scalar(@{ $results }) > 0) ? 1 : 0;
}
=item query( )
=cut
sub query {
my $self = shift;
throw ODO::Exception::Runtime(error=> 'Missing query string')
unless($self->queryString());
my $rdf_map = "rdf for <${ODO::Ontology::RDFS::Vocabulary::RDF}>";
my $rdfs_map = "rdfs for <${ODO::Ontology::RDFS::Vocabulary::RDFS}>";
my $qs_rdql = 'SELECT ?stmt WHERE ' . $self->queryString() . " USING $rdf_map, $rdfs_map";
my $results = $self->issueQuery( $qs_rdql );
my $objects = [];
while(@{ $results }) {
my $r = shift @{ $results };
my $object = ref $self;
push @{ $objects }, $object->new($r->subject(), $self->graph());
}
return (wantarray) ? @{ $objects } : $objects;
}
sub getPropertyFromGraph {
my ($self, $propertyPackageName) = @_;
throw ODO::Exception::Parameter::Missing(error=> 'Missing property package name')
unless($propertyPackageName);
# Only Resources can have properties
throw ODO::Exception::Runtime(error=> 'Subject is not a ODO::Graph::Node::Resource')
unless($self->subject()->isa('ODO::Graph::Node::Resource'));
throw ODO::Exception::Runtime(error=> 'Missing ODO::Graph object')
unless($self->graph());
my $propertyQueryString = $propertyPackageName->queryString();
throw ODO::Exception::Runtime(error=> 'Missing property query string')
unless($propertyQueryString);
my $propertyTripleMatch = ODO::Query::Simple::Parser->parse($propertyQueryString);
# FIXME: Probably good enough for now
$propertyTripleMatch = $propertyTripleMatch->[0];
# Create a triple match that can get all of _THIS_ object's
# instances of the specific property.
$propertyTripleMatch->subject($self->subject());
$propertyTripleMatch->predicate($propertyTripleMatch->object());
$propertyTripleMatch->object( $ODO::Node::ANY );
my $results = $self->graph()->query($propertyTripleMatch)->results();
my $objects = [];
while(@{ $results }) {
my $r = shift @{ $results };
push @{ $objects }, $propertyPackageName->new($r->object(), $self->graph());
}
return (wantarray) ? @{ $objects } : $objects;
}
sub issueQuery {
my ($self, $query) = @_;
my $result_set = $self->graph()->query($query);
my $results = $result_set->results();
return (wantarray) ? @{ $results } : $results;
}
sub init {
my ($self, $config) = @_;
$self->params($config, @METHODS);
$self->{'propertyURIMap'} = {};
# Hashes that will store property cardinality information
$self->{'min_cardinality'} = {};
$self->{'max_cardinality'} = {};
# FIXME: This is an instance and hence is an Individual of a class
unshift @ISA, 'ODO::Ontology::OWL::Lite::Individual';
return $self;
}
package ODO::Ontology::OWL::Lite::Thing::PropertiesContainer;
package ODO::Ontology::OWL::Lite::NoThing;
use vars qw( @ISA );
@ISA = ( );
package ODO::Ontology::OWL::Lite::NoThing::PropertiesContainer;
use vars qw( @ISA );
@ISA = ( );
package ODO::Ontology::OWL::Lite::Individual;
# Objects are owl:Individuals iff they are instantiated types
package ODO::Ontology::OWL::Lite::ObjectProperty;
package ODO::Ontology::OWL::Lite::DatatypeProperty;
package ODO::Ontology::OWL::Lite::AnnotationProperty;
1;
__END__