#!/usr/bin/perl
use common::sense;
use CGI;
use CGI::Carp 'fatalsToBrowser';
use RDF::Trine;
use RDF::RDFa::Generator;
use WordNet::QueryData;
my $wn = WordNet::QueryData->new;
my $cgi = CGI->new;
my $data = {};
my $input = rdfuri_partdecode($cgi->param('noun'));
my @senses = $wn->querySense($input.'#n');
if (!@senses)
{
print $cgi->header(-status=>404, -type=>'text/plain');
print "Not found." and exit;
}
sub NS ($)
{
my $pfx = shift;
return sub {
my $sfx = shift;
return $pfx.$sfx;
};
}
my $SKOS = NS 'http://www.w3.org/2004/02/skos/core#';
my $OWL = NS 'http://www.w3.org/2002/07/owl#';
my $FOAF = NS 'http://xmlns.com/foaf/0.1/';
my $RDF = NS 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
my $RDFS = NS 'http://www.w3.org/2000/01/rdf-schema#';
my $WN = NS 'http://ontologi.es/WordNet/vocab#';
my $GCLASS = rdfuri_for_generalclass($input);
my $G_count = 0;
push @{ $data->{ $GCLASS }{$RDF->('type')} },
{
value => $RDFS->('Class'),
type => 'uri',
};
push @{ $data->{ $GCLASS }{$OWL->('equivalentClass')} },
{
value => 'http://xmlns.com/wordnet/1.6/'.rdfuri_partencode($input),
type => 'uri',
};
push @{ $data->{ $GCLASS }{$RDFS->('label')} },
{
value => ucwords($input),
lang => 'en',
type => 'literal',
};
my $n = ($input =~ /^[aeiou]/i) ? 'n' : '';
push @{ $data->{ $GCLASS }{$RDFS->('comment')} },
{
value => "Instances of this class are (roughly speaking) those things where it's correct to say 'this is a${n} " . ucwords($input) . "', for any reasonable interpretation of the word '" . ucwords($input) . "'.",
lang => 'en',
type => 'literal',
};
push @{ $data->{ $GCLASS }{$OWL->('unionOf')} },
{
value => '_:list' . $G_count,
lang => 'en',
type => 'blank',
};
push @{ $data->{ $WN->('WordNet30') }{$RDF->('type')} },
{
value => $SKOS->('ConceptScheme'),
type => 'uri',
};
push @{ $data->{ $WN->('WordNet30') }{$RDFS->('label')} },
{
value => "WordNet 3.0",
lang => 'en',
type => 'literal',
};
push @{ $data->{ $WN->('WordNet30') }{$RDFS->('comment')} },
{
value => "WordNet 3.0 Copyright 2006 by Princeton University. All rights reserved. THIS SOFTWARE AND DATABASE IS PROVIDED \"AS IS\" AND PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES OF MERCHANT- ABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE, DATABASE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.",
lang => 'en',
type => 'literal',
};
foreach my $sense (@senses)
{
my @syns = $wn->querySense($sense, "syns");
my %labels = map {
(my $label = [$_ =~ m/^([^#]+)/]->[0]) =~ s/_/ /g;
$_ => $label; } @syns;
my $CONCEPT = rdfuri_for_concept($syns[0]);
my $CLASS = rdfuri_for_class($syns[0]);
push @{ $data->{ '_:list' . $G_count }{$RDF->('type')} },
{
value => $RDF->('List'),
type => 'uri',
};
push @{ $data->{ '_:list' . $G_count }{$RDF->('first')} },
{
value => $CLASS,
type => 'uri',
};
push @{ $data->{ '_:list' . $G_count }{$RDF->('rest')} },
{
value => '_:list' . (++$G_count),
type => 'blank',
};
push @{ $data->{ $CONCEPT }{$RDF->('type')} },
{
value => $SKOS->('Concept'),
type => 'uri',
};
push @{ $data->{ $CONCEPT }{$FOAF->('focus')} },
{
value => $CLASS,
type => 'uri',
};
push @{ $data->{ $CONCEPT }{$SKOS->('prefLabel')} },
{
value => $labels{ $syns[0] },
lang => 'en',
type => 'literal',
};
push @{ $data->{ $CONCEPT }{$SKOS->('altLabel')} },
map
{
{
value => $labels{ $_ },
lang => 'en',
type => 'literal',
}
} @syns[1 .. $#syns];
push @{ $data->{ $CONCEPT }{$SKOS->('notation')} },
map
{
{
value => $_,
datatype => $WN->('wn3'),
type => 'literal',
}
} @syns;
push @{ $data->{ $CONCEPT }{$SKOS->('definition')} },
{
value => $wn->querySense($sense, "glos"),
lang => 'en',
type => 'literal',
};
push @{ $data->{ $CONCEPT }{$SKOS->('broaderTransitive')} },
map
{
{
value => rdfuri_for_concept($_),
type => 'uri',
}
}
$wn->querySense($sense, "hype");
push @{ $data->{ $CONCEPT }{$SKOS->('narrowerTransitive')} },
map
{
{
value => rdfuri_for_concept($_),
type => 'uri',
}
}
$wn->querySense($sense, "hypo");
push @{ $data->{ $CONCEPT }{$WN->('meronym')} },
map
{
{
value => rdfuri_for_concept($_),
type => 'uri',
}
}
$wn->querySense($sense, "mero");
push @{ $data->{ $CONCEPT }{$WN->('holonym')} },
map
{
{
value => rdfuri_for_concept($_),
type => 'uri',
}
}
$wn->querySense($sense, "holo");
push @{ $data->{ $CONCEPT }{$WN->('antonym')} },
map
{
{
value => rdfuri_for_concept($_),
type => 'uri',
}
}
$wn->querySense($sense, "ants");
push @{ $data->{ $CONCEPT }{$SKOS->('inScheme')} },
{
value => $WN->('WordNet30'),
type => 'uri',
};
push @{ $data->{ $CLASS }{$RDF->('type')} },
{
value => $RDFS->('Class'),
type => 'uri',
};
push @{ $data->{ $CLASS }{$RDFS->('label')} },
{
value => $labels{ $syns[0] },
lang => 'en',
type => 'literal',
};
push @{ $data->{ $CLASS }{$RDFS->('comment')} },
{
value => $wn->querySense($sense, "glos"),
lang => 'en',
type => 'literal',
};
push @{ $data->{ $CLASS }{$RDFS->('subClassOf')} },
{
value => $GCLASS,
type => 'uri',
};
push @{ $data->{ $CLASS }{$RDFS->('seeAlso')} },
{
value => $CONCEPT,
type => 'uri',
};
push @{ $data->{ $CLASS }{$RDFS->('subClassOf')} },
map
{
{
value => rdfuri_for_class($_),
type => 'uri',
}
}
$wn->querySense($sense, "hypes");
}
$data->{ '_:list' . ($G_count-1) }{$RDF->('rest')}[0] =
{
value => $RDF->('nil'),
type => 'uri',
};
my $model = RDF::Trine::Model->temporary_model;
$model->add_hashref($data);
my $ser = RDF::Trine::Serializer->negotiate(namespaces=>{
skos => 'http://www.w3.org/2004/02/skos/core#',
foaf => 'http://xmlns.com/foaf/0.1/',
rdfs => 'http://www.w3.org/2000/01/rdf-schema#',
wn => 'http://ontologi.es/WordNet/concept/',
class => 'http://ontologi.es/WordNet/class/',
wnv => 'http://ontologi.es/WordNet/vocab#',
owl => 'http://www.w3.org/2002/07/owl#',
},
style => 'HTML::Pretty',
title => ucwords($input),
);
if ($ser->can('media_types'))
{
print $cgi->header([$ser->media_types]->[0]);
}
elsif ((ref $ser) =~ /RDFa/i)
{
print $cgi->header(
-type=>'text/html;charset=utf-8',
-link=>'</WordNet/style.css>;rel="stylesheet";type="text/css"',
);
}
else
{
print $cgi->header('application/octet-stream');
}
print $ser->serialize_model_to_string($model) and exit;
sub ucwords ($)
{
(my $str = lc shift) =~ s/\b(\w)/\u$1/g;
return $str;
}
sub rdfuri_partdecode
{
my $r = lc shift;
$r =~ s/_/ /g;
return $r;
}
sub rdfuri_partencode
{
my $r = lc shift;
$r =~ s/_/ /g;
$r = ucwords $r;
$r =~ s/ /_/g;
return $r;
}
sub rdfuri_for_concept
{
my ($word, undef, $sense) = split /#/, shift;
return 'http://ontologi.es/WordNet/concept/' . rdfuri_partencode($word) . "-" . $sense;
}
sub rdfuri_for_class
{
my ($word, undef, $sense) = split /#/, shift;
return 'http://ontologi.es/WordNet/class/' . rdfuri_partencode($word) . "-" . $sense;
}
sub rdfuri_for_generalclass
{
my ($word, undef, $sense) = split /#/, shift;
return 'http://ontologi.es/WordNet/class/' . rdfuri_partencode($word);
}