当我尝试使用Jena的OntModel等API修改我的OWL文件时,我遇到了问题。原始的OWL文件是:
<owl:Class rdf:about="file:///c:/onto_for_code_test/test.owl#DevelopmentProject" />
<owl:ObjectProperty rdf:about="file:///c:/onto_for_code_test/test.owl#carriesOut" />
<owl:FunctionalProperty rdf:about="hasProgramme">
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty" />
</owl:FunctionalProperty>
我想将功能对象属性更改为非功能对象属性,但我无法找到有关此功能的任何API。所需的OWL文件是:
<owl:Class rdf:about="file:///c:/onto_for_code_test/test.owl#DevelopmentProject" />
<owl:ObjectProperty rdf:about="file:///c:/onto_for_code_test/test.owl#carriesOut" />
<owl:ObjectProperty rdf:about="hasProgramme" />
以下代码为我提供了我想要的OWL:
OntModel otm = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
otm.read(DIRECTORY, null);
ObjectProperty hasProgramme = otm.getProperty(NS + "hasProgramme");
hasProgramme.removeProperty(RDF.type, OWL.FunctionalProperty);`
但是,当我想再次将hasProgramme
转换为功能属性时,
使用hasProgramme.convertToFunctionalProperty();
不会将hasProgramme rdf:type owl:FunctionalProperty
添加回模型!因此,我认为在这种情况下使用hasProgramme.removeProperty(RDF.type, OWL.FunctionalProperty);
必须是不正确的。将功能ObjectProperty转换为非功能属性的正确方法是什么?
答案 0 :(得分:3)
Jena用于实现convertToFunctionalProperty(以及其他多态行为)的方法使用了大量缓存。通过更改基础模型,您违反了缓存所做的一些假设。看起来使属性不起作用的正确方法是
p.removeProperty( RDF.type, OWL.FunctionalProperty );
你已经完成了。要使其再次起作用,请再次添加类型:
p.addProperty( RDF.type, OWL.FunctionalProperty );
我做了一个快速搜索,并没有找到任何将功能属性变成不属于功能属性的东西。我认为您的方法是正确的:删除prop a owl:FunctionalProperty
看起来是正确的方法。
OntProperty界面中有许多方法用于在其他类型的属性中转换属性,但不能使它们不某些类型的属性。特别是,convertToFunctional方法表示它将:
回答此属性的一个方面作为功能属性 如有必要,可为模型提供其他信息。
返回:此属性,但转换为FunctionalProperty构面
然而,你成功地使不成为一个功能属性,看起来convertToFunctional 应该再次使其正常工作。然而,你说那个
但是,当我想将hasProgramme再次转换为功能时, hasProgramme.convertToFunctionalProperty();不起作用。
你并没有提供足够的信息,说明什么&#34;不起作用&#34;意味着那里,但这里有一个例子,我想,你的意思是什么。令人惊讶的是,第一次拨打convertToFunctionalProperty
会添加hasProgram rdf:type owl:FunctionalProperty
三联,但如果您手动将其删除,则第二次通话不会再将其添加回来!
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDF;
public class FunctionalPropertyExample {
public static void main(String[] args) {
String ns = "http://stackoverflow.com/q/23507335/1281433/";
OntModel model = ModelFactory.createOntologyModel( OntModelSpec.OWL_DL_MEM );
ObjectProperty opHasProgram = model.createOntProperty( ns+"hasProgram" ).convertToObjectProperty();
System.out.println( "<!-- Model with plain ObjectProperty-->" );
RDFDataMgr.write( System.out, model, Lang.RDFXML );
opHasProgram.convertToFunctionalProperty();
System.out.println( "\n<!-- Model with FunctionalProperty-->" );
RDFDataMgr.write( System.out, model, Lang.RDFXML );
opHasProgram.removeProperty( RDF.type, OWL.FunctionalProperty );
System.out.println( "\n<!-- Model with ObjectProperty again-->" );
RDFDataMgr.write( System.out, model, Lang.RDFXML );
opHasProgram.convertToFunctionalProperty();
System.out.println( "\n<!-- Model with FunctionalProperty again -->" );
RDFDataMgr.write( System.out, model, Lang.RDFXML );
}
}
<!-- Model with plain ObjectProperty-->
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:ObjectProperty rdf:about="http://stackoverflow.com/q/23507335/1281433/hasProgram">
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</owl:ObjectProperty>
</rdf:RDF>
<!-- Model with FunctionalProperty-->
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:FunctionalProperty rdf:about="http://stackoverflow.com/q/23507335/1281433/hasProgram">
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</owl:FunctionalProperty>
</rdf:RDF>
<!-- Model with ObjectProperty again-->
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:ObjectProperty rdf:about="http://stackoverflow.com/q/23507335/1281433/hasProgram">
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</owl:ObjectProperty>
</rdf:RDF>
<!-- Model with FunctionalProperty again -->
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:ObjectProperty rdf:about="http://stackoverflow.com/q/23507335/1281433/hasProgram">
<!-- *** there should be an rdf:type owl:FunctionalProperty assertion here! *** -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</owl:ObjectProperty>
</rdf:RDF>
这很奇怪。为了弄清楚发生了什么,我们需要看一下实现,但我认为答案归结为缓存。 OntPropertyImpl实现了convertToFunctionalProperty(我们将跟随链):
public FunctionalProperty convertToFunctionalProperty() {
return convertToType( getProfile().FUNCTIONAL_PROPERTY(), "FUNCTIONAL_PROPERTY", FunctionalProperty.class );
}
然后,在OntResourceImpl:
protected <T extends RDFNode> T convertToType( Resource type, String name, Class<T> cls ) {
checkProfile( type, name );
if (canAs( cls )) {
// don't need to update the model, we already can do the given facet
return as( cls );
}
// we're told that adding this rdf:type will make the as() possible - let's see
addProperty( RDF.type, type );
return as( cls );
}
因此,如果 canAs( FunctionalProperty.class )
返回false,我们会看到该属性将被添加。所以出于某种原因,即使在我们删除了指示该属性是FunctionalProperty的三元组之后,它仍然返回true。在EnhNode:
public <X extends RDFNode> boolean canAs( Class<X> t )
{ return canSupport( t ); }
// ...
protected <X extends RDFNode> boolean canSupport( Class<X> t )
{
if (alreadyHasView( t )) return true;
if (getGraph() == null) return false;
Implementation imp = getPersonality().getImplementation( t );
return imp == null ? false : imp.canWrap( asNode(), getGraph() );
}
现在,我们无法确定,但alreadyHasView( t )
在这里看起来很可疑。毕竟, 已经有了一个FunctionalProperty视图。现在,在多态:
protected <X extends T> boolean alreadyHasView( Class<X> t )
{ return findExistingView( t ) != null; }
/**
find an existing view in the ring which is an instance of _t_ and
return it; otherwise return null. If _this_ is an instance, the
search takes care to find it first.
*/
private <X extends T> X findExistingView( Class<X> t )
{
Polymorphic<T> r = this;
for (;;)
{
if (t.isInstance( r ) && r.isValid()) return t.cast( r );
r = r.ring;
if (r == this) return null;
}
}
我们没有足够的背景知道为什么 findExistingView
正在返回非null
。为此,我们需要查看addView
,它首先添加了它。实施并不是真正重要的部分;问题是这些视图正在缓存,并且canAs
不会重构到模型中,以便查看模型中是否仍存在必要的数据。
大多数时候,这可能是有道理的。毕竟,如果你能够转换过去的东西,你仍然可以引用这些对象。如果修改基础模型,那么这些对象现在代表什么?如果您尝试使用它们会发生什么?它们依赖于正常运行的一些数据可能不再存在于数据中。例如,如果您有一个OntClass并删除c rdf:type owl:Class
三元组,那么当您尝试使用c
时会发生什么?在每次使用时进行健全性检查都太昂贵了。如果从某些其他来源推断某些必要的数据,这可能特别坏。
我认为这里的解决方案是,如果你想修改模型,那么使用更高级别的OntModel API可能是危险的,因为它的大部分依赖于缓存,你将会失效。如果是这种情况,我认为仍然可以通过删除三元组prop rdf:type owl:FunctionalProperty
来使一个属性不起作用。它只是而不是使用convertToFunctionalProperty
,您应该再次添加三联prop rdf:type owl:FunctionalProperty
。