Using OWL API, how to get class or individual name - semantic-web

I can get OWLClass and access the information. The classes and individuals are along with prefix.
Is there any method to get rid of prefix?
For example:
OWLClass cls = factory.getOWLClass(":Person", pm);
for (OWLIndividual indiv : cls.getIndividuals(onto)) {
System.out.println(indiv.toString());
}
print:
<http://www.co-ode.org/ontologies/ont.owl#Mon>
<http://www.co-ode.org/ontologies/ont.owl#Dad>
What I want is just Mon Dad
UPDATE:
Thank you Ignazio.
I found that the key is getIRI() method.
for (OWLIndividual indiv : owlclass.getIndividuals(onto)) {
System.out.println(indiv.asOWLNamedIndividual().getIRI().getFragment());
}
for (OWLClassExpression expre : owlclass.getSubClasses(onto)) {
System.out.println(expre.asOWLClass().getIRI().getFragment());
}

For entities, you can do this with OWLEntity.getIRI().getFragment().
Note however that not all entities have a name of this kind, as an Iri can legitimately end with / or #

A little update : getFragment() is deprecated now. I use getShortForm() instead.

I have faced the same problem and used OWLEntity.getIRI().getShortForm().

I retrieved class names into a List as follows
get ontology from the disk and assign to variable o Type ;
OWLOntology o;
And Created list to add Classes as follows
List listofClass = new ArrayList();
Then add the following codes
Collection<OWLClass> classes = o.getClassesInSignature();
//getting class names in the ontology
for (OWLClass owlClass : classes) {
System.out.println(owlClass.getIRI().getShortForm());
listofClass.add(owlClass.getIRI().getShortForm());
}
return listofClass;
}

Related

Possible to create class aliases dynamically?

Got this class:
class Mass-lb is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('lb'),
:base_value(453.59237),
:$value,
);
}
}
I have created aliases like this:
class Mass-lbs is Mass-lb { }
class Mass-pound is Mass-lb { }
class Mass-pounds is Mass-lb { }
class Mass-pnds is Mass-lb { }
But I'd prefer to do something like this:
my #lb-syn = < lbs pounds pound pnds >;
for #lb-syn {
EVAL 'class ::("Mass-$_") is Mass-lb {}';
}
This throws an error:
Name ::("Mass-$_") is not compile-time known, and can not serve as a package name
PHP has a built-in for creating aliases: https://www.php.net/manual/en/function.class-alias.php
I couldn't find anything similar for raku.
In RakuAST there's a class that you can call to create a new type. But that the RakuAST branch hasn't landed yet.
Until then, your approach using EVAL is valid, you just need to make it a bit simpler:
class Mass-lb { }
BEGIN "constant Mass-$_ = Mass-lb".EVAL
for <lbs pounds pound pnds>;
my $mlb = Mass-lbs.new;
Make sure the aliases are created at BEGIN time.
No need to subclass, you can use a constant for aliasing.
Since constants are our by default, they're visible outside of the EVAL.
Alternatively, you could use raku Physics::Unit and Physics::Measure...
use Physics::Unit;
use Physics::Measure :ALL;
# define a new custom Unit
Unit.new( defn => 'lbm', names => <Mass-lb Mass-lbs Mass-pound Mass-pounds Mass-pnds> );
say GetUnit('Mass-lbs').names; #[Mass-lb Mass-lbs Mass-pound Mass-pounds Mass-pnds]
# use the Unit in a Measure
my $mass = ♎️'42 Mass-pnds';
say $mass; #42Mass-lb
say $mass.^name; #(..Mass) ...class name
# convert to another Unit
my $kgm = $mass.in: 'kg';
say $kgm; #19.05087954kg
# convert back
say $kgm.in: 'Mass-pound'; #42Mass-lb
# raku Rats mean that the back conversion is identical
say $kgm cmp $mass; #Same
# with % or abs Error
my $mass2 = ♎️'42 Mass-pnds ±3%';
say $mass2; #42Mass-lb ±1.26
say $mass2.in: 'kg'; #19.05087954kg ±0.5715263862
More info at github Physics::Unit and Physics::Measure...

Elm: accessing common fields in union

I am trying to model a type as a union where each member of that union has properties in common with all other members.
I am currently achieving this like so:
type alias File = {
name : String
}
type CommonFileState extra = CommonFileState {
id : String
, file : File
} extra
type alias ValidFileState = CommonFileState {
validatedAt : Int
}
type alias InvalidFileState = CommonFileState {
reason : String
}
type alias LoadingFileState = CommonFileState {}
type FileState = Valid ValidFileState | Invalid InvalidFileState | Loading LoadingFileState
Now if I want to read one of those common properties on any given FileState, I must match against each member of the union:
getId : FileState -> String
getId fileState = case fileState of
Valid (CommonFileState {id} extra) -> id
Invalid (CommonFileState {id} extra) -> id
Loading (CommonFileState {id} extra) -> id
This feels wrong to me, because I have to duplicate the property access for each member. If I needed to manipulate this property somehow (e.g. concatenating something onto the string), I would also have to duplicate this.
I want to be able to easily access common properties of my union, and operate on those common properties.
When I started searching for other ways to do this, I found one alternative was to nest the union inside a record, which also holds the common properties:
type alias ValidCurrentFileState = {
validatedAt : Int
}
type alias InvalidCurrentFileState = {
reason : String
}
type alias LoadingCurrentFileState = {}
type CurrentFileState = Valid ValidCurrentFileState | Invalid InvalidCurrentFileState| Loading LoadingCurrentFileState
type alias File = {
name : String
}
type alias FileState = {
id : String
, file : File
, currentState : CurrentFileState
}
getId : FileState -> String
getId {id} = id
However this is awkward because I have to name the nested union, which adds a level of unnecessary indirection: "file state" and "current file state" are conceptually the same.
Are there any other ways of doing this which don't have the problems I mentioned?
I think you are thinking about this the wrong way around.
The purpose of modelling (in Elm) is capture the possible states of your data, and to exclude - in your model - 'impossible' states, so that the compiler can statically prevent the code every creating such states.
Once you're happy with your model, you write the helpers you need to make your core logic easy to express and to maintain.
I suspect I would normally go with your second approach, but I don't know all the issues you need to account for.

Perl 6 multi methods never match expected signature

I have a class with two multi methods (multi submit).
I call my multi like this:
$perspective.submit(:message($message.content));
Which gets shipped off to my class:
my $perspective-api = API::Perspective.new(:api-key(%*ENV<PERSPECTIVE_API_KEY>));
proto method submit (|) {*}
multi method submit(Str :$message!, MODEL :#models = TOXICITY) {
my $score = $perspective-api.analyze(:#models, :comment($message));
say #models Z=> $score<attributeScores>{#models}.map: *<summaryScore><value>;
multi method submit(Str :$name!, MODEL :#models = TOXICITY) {
my $score = $perspective-api.analyze(:#models, :comment($name));
say #models Z=> $score<attributeScores>{#models}.map: *<summaryScore><value>;
}
However I always get the following response:
Died because of the exception:
Cannot resolve caller AUTOGEN(Rose::ContentAnalysis::Perspective:D: :message(Str)); none of these signatures match:
(Rose::ContentAnalysis::Perspective: Str :$message!, MODEL :#models = MODEL::TOXICITY, *%_)
(Rose::ContentAnalysis::Perspective: Str :$name!, MODEL :#models = MODEL::TOXICITY, *%_)
Despite my named argument (:message) being a Str as required and #models having a default declared.
Multiple dispatch works in two phases:
Considering the number of positional parameters and their types
If there are any where clauses, named parameters, or sub-signatures, doing a test bind of the signature to see if it would match
The second phase will reject the candidate if it fails to bind for any reason. One such reason, and I believe the cause of the issue here, is that the default value is wrongly typed. For example, in:
multi m(:#x = "not-an-array") { }
m()
We get an error:
Cannot resolve caller m(...); none of these signatures match:
(:#x = "not-an-array")
in block <unit> at -e line 1
But changing it to:
multi m(:#x = ["an-array"]) { }
m()
Works fine. (Note that while a default value uses =, it's actually a binding, not an assignment.)
In the case in the question there's this:
MODEL :#models = TOXICITY
Looking at the module source the code is taken from, I see:
enum MODEL is export (
<TOXICITY SEVERE_TOXICITY TOXICITY_FAST IDENTITY_ATTACK
INSULT PROFANITY SEXUALLY_EXPLICIT THREAT FLIRTATION
ATTACK_ON_AUTHOR ATTACK_ON_COMMENTER INCOHERENT INFLAMMATORY
LIKELY_TO_REJECT OBSCENE SPAM UNSUBSTANTIAL>
);
Thus TOXICITY is just an Int, but what's expected is a typed array of MODEL values.
Thus, if you do this:
multi method submit(Str :$message!, MODEL :#models = Array[MODEL](TOXICITY)) {
It should work.
I see two issues.
One is that you have two methods that are identical except for the name of one named parameter.
Named parameters can have aliases:
# V--------------V
multi method submit(Str :name(:$message)!, MODEL :#models = TOXICITY) {
my $score = $perspective-api.analyze(:#models, :comment($message));
say #models Z=> $score<attributeScores>{#models}.map: *<summaryScore><value>;
}
Note that :$message is really short for :message($message)
Now on the problem which actually prevents your code from working.
#models is a Positional, but you are assigning it a singular value in the signature.
Assign it a Positional, and it works:
(In this case it has to be of type Array[MODEL] because of the MODEL type declaration.)
# V---------------------V
multi method submit(Str :name(:$message)!, MODEL :#models = Array[MODEL](TOXICITY,)) {
my $score = $perspective-api.analyze(:#models, :comment($message));
say #models Z=> $score<attributeScores>{#models}.map: *<summaryScore><value>;
}

HibernateException: Errors in named query

When running a particular unit-test, I am getting the exception:
Caused by: org.hibernate.HibernateException: Errors in named queries: UPDATE_NEXT_FIRE_TIME
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:437)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891)
... 44 more
for the named query defined here:
#Entity(name="fireTime")
#Table(name="qrtz_triggers")
#NamedQueries({
#NamedQuery(
name="UPDATE_NEXT_FIRE_TIME",
query= "update fireTime t set t.next_fire_time = :epochTime where t.trigger_name = 'CalculationTrigger'")
})
public class JpaFireTimeUpdaterImpl implements FireTimeUpdater {
#Id
#Column(name="next_fire_time", insertable=true, updatable=true)
private long epochTime;
public JpaFireTimeUpdaterImpl() {}
public JpaFireTimeUpdaterImpl(final long epochTime) {
this.epochTime = epochTime;
}
#Override
public long getEpochTime() {
return this.epochTime;
}
public void setEpochTime(final long epochTime) {
this.epochTime = epochTime;
}
}
After debugging as deep as I could, I've found that the exception occurs in w.statement(hqlAst) in QueryTranslatorImpl:
private HqlSqlWalker analyze(HqlParser parser, String collectionRole) throws QueryException, RecognitionException {
HqlSqlWalker w = new HqlSqlWalker( this, factory, parser, tokenReplacements, collectionRole );
AST hqlAst = parser.getAST();
// Transform the tree.
w.statement( hqlAst );
if ( AST_LOG.isDebugEnabled() ) {
ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class );
AST_LOG.debug( printer.showAsString( w.getAST(), "--- SQL AST ---" ) );
}
w.getParseErrorHandler().throwQueryException();
return w;
}
Is there something wrong with my query or annotations?
NamedQuery should be written with JPQL, but query seems to mix both names of persistent attributes and names of database columns. Names of database columns cannot be used in JPQL.
In this case instead of next_fire_time name of the persistent attribute epochTime should be used. Also trigger_name looks more like name of the database column than name of the persistent attribute, but it seems not to be mapped in your current class at all. After it is mapped, query is as follows:
update fireTime t set t.epochTime = :epochTime
where t.triggerName = 'CalculationTrigger'
If SQL query is preferred, then #NamedNativeQuery should be used instead.
As a side note, JPA 2.0 specification doesn't encourage changing primary key:
The application must not change the value of the primary key[10]. The
behavior is undefined if this occurs.[11]
In general entities are not aware of changed made via JPQL queries. That gets especially interesting when trying to refresh entity that does not exist anymore (because primary key was changed).
Additionally naming is little bit confusing:
Name of the class looks more like name of the service class
than name of the entity.
Starting name of the entity with lower
case letter is rather rare style.
Name of the entity, name of the
table and name of the class do not match too well.

SQL to Magento model understanding

Understanding Magento Models by reference of SQL:
select * from user_devices where user_id = 1
select * from user_devices where device_id = 3
How could I perform the same using my magento models? getModel("module/userdevice")
Also, how can I find the number of rows for each query
Following questions have been answered in this thread.
How to perform a where clause ?
How to retrieve the size of the result set ?
How to retrieve the first item in the result set ?
How to paginate the result set ? (limit)
How to name the model ?
You are referring to Collections
Some references for you:
http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-5-magento-models-and-orm-basics
http://alanstorm.com/magento_collections
http://www.magentocommerce.com/wiki/1_-_installation_and_configuration/using_collections_in_magento
lib/varien/data/collection/db.php and lib/varien/data/collection.php
So, assuming your module is set up correctly, you would use a collection to retrieve multiple objects of your model type.
Syntax for this is:
$yourCollection = Mage::getModel('module/userdevice')->getCollection()
Magento has provided some great features for developers to use with collections. So your example above is very simple to achieve:
$yourCollection = Mage::getModel('module/userdevice')->getCollection()
->addFieldToFilter('user_id', 1)
->addFieldToFilter('device_id', 3);
You can get the number of objects returned:
$yourCollection->count() or simply count($yourCollection)
EDIT
To answer the question posed in the comment: "what If I do not require a collection but rather just a particular object"
This depends if you still require both conditions in the original question to be satisfied or if you know the id of the object you wish to load.
If you know the id of the object then simply:
Mage::getModel('module/userdevice')->load($objectId);
but if you wish to still load based on the two attributes:
user_id = 1
device_id = 3
then you would still use a collection but simply return the first object (assuming that only one object could only ever satisfy both conditions).
For reuse, wrap this logic in a method and place in your model:
public function loadByUserDevice($userId, $deviceId)
{
$collection = $this->getResourceCollection()
->addFieldToFilter('user_id', $userId)
->addFieldToFilter('device_id', $deviceId)
->setCurPage(1)
->setPageSize(1)
;
foreach ($collection as $obj) {
return $obj;
}
return false;
}
You would call this as follows:
$userId = 1;
$deviceId = 3;
Mage::getModel('module/userdevice')->loadByUserDevice($userId, $deviceId);
NOTE:
You could shorten the loadByUserDevice to the following, though you would not get the benefit of the false return value should no object be found:
public function loadByUserDevice($userId, $deviceId)
{
$collection = $this->getResourceCollection()
->addFieldToFilter('user_id', $userId)
->addFieldToFilter('device_id', $deviceId)
;
return $collection->getFirstItem();
}