Jena's OntModel has a method listHierarchyRootClasses that returns an iterator over the classes in this ontology model that represent the uppermost nodes of the class hierarchy. But why does OntModel have no method of the same function for the semantic properties? There is a property hierarchy as well, so why developers make a listHierarchyRootProperties?
I have solved this by using listAllOntProperties method, but it is a workaround, and does not look good. I don't understand why is it necessary. What is the reason?
Jena is an open-source project. You are more than welcome to submit a patch with the additional functionality you would like to see in the library. Please submit patches via the Jira account.
To answer your direct question: there's no particular reason why there's no equivalent for the property hierarchy. However, property inheritance isn't as widely used as as class inheritance in OWL, and in all the years since I wrote listHierarchyRootClasses, you're the first person I can remember asking about the property hierarchy.
Here is my workaround, which produces alphabetically sorted hierarchy (tree) of semantic properties. The getPropertyTreeModel() method returns a model for an ice:tree component and the parameter domContent is not important (it is for my special needs):
protected static DefaultTreeModel getPropertyTreeModel(OntModel ontModel, Document domContent) {
System.out.println("Creating property model...");
DefaultMutableTreeNode rootTreeNode = getRoot();
DefaultTreeModel treeModel = new DefaultTreeModel(rootTreeNode);
Iterator i = getAlphabeticalIterator(ontModel.listAllOntProperties().filterDrop(new Filter() {
#Override
public boolean accept(Object o) {
return !((OntProperty) o).listSuperProperties(true).toList().isEmpty();
}
}));
while (i.hasNext()) {
joinResource(rootTreeNode, (OntProperty) i.next(), new ArrayList(), OntProperty.class, domContent);
}
return treeModel;
}
private static Iterator getAlphabeticalIterator(ExtendedIterator ei) {
List l = ei.toList();
Collections.sort(l, new Comparator<OntResource>() {
#Override
public int compare(OntResource o1, OntResource o2) {
return (o1.getLocalName().compareTo(o2.getLocalName()));
}
});
return l.iterator();
}
private static DefaultMutableTreeNode getRoot() {
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
ClassNodeUserObject rootObject = new ClassNodeUserObject(rootTreeNode);
rootObject.setExpanded(true);
rootTreeNode.setUserObject(rootObject);
return rootTreeNode;
}
private static void joinResource(DefaultMutableTreeNode parent, OntResource res, List occurs, Class c, Document domContent) {
DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
SemanticNodeUserObject branchObject = (c.equals(OntClass.class))
? new ClassNodeUserObject(branchNode) : new PropertyNodeUserObject(branchNode);
branchObject.setOntResource(res);
branchObject.setExpanded(false);
branchObject.setLeaf(true);
// optimalizace: v pripade prazdneho souboru bez parsovani, aktualizace barev
if (domContent != null) {
setColorToNode(branchObject, domContent);
}
branchNode.setUserObject(branchObject);
parent.add(branchNode);
// rekurze
if (res.canAs(c) && !occurs.contains(res)) {
ExtendedIterator ei = (c.equals(OntClass.class)) ? ((OntClass) res).listSubClasses(true)
: ((OntProperty) res).listSubProperties(true);
branchObject.setLeaf(!ei.hasNext());
for (Iterator i = getAlphabeticalIterator(ei); i.hasNext();) {
OntResource sub = (OntResource) i.next();
occurs.add(res);
joinResource(branchNode, sub, occurs, c, domContent);
occurs.remove(res);
}
}
}
Related
How can I exclude the child domain property when I use the grailsWebDataBinder?
For example, I have domains:
class Car {
String carPropertyToExclude
Set<Detail> details
static hasMany = [details: Detail]
}
class Detail {
String detailPropertyToExclude
static belongsTo= [car: Car]
}
I want to exclude the detailPropertyToExclude from Detail when I call the bind method of grailsWebDataBinder and give the car instance as a parameter
Code:
List blackList = ["carPropertyToExclude"]
grailsWebDataBinder.bind(car, new SimpleMapDataBindingSource(params), null, blackList)
Note:
Don't suggest the bindable: false or variants when excluded from anywhere. Only need to know is there a way to do it by providing blackList as bind() method parameter.
These variants also not working:
List blackList = ["carPropertyToExclude", "details.detailPropertyToExclude"]
List blackList = ["carPropertyToExclude", [Detail.class : "detailPropertyToExclude"]]
The main question is how to prepare the blackList to exclude also child's property?
blacklist parameter supports only direct object properties
you can use DataBindingListener
import grails.databinding.events.DataBindingListenerAdapter
class BlackListener extends DataBindingListenerAdapter{
List<String> list
//returns false if you want to exclude property from binding
public Boolean beforeBinding(Object obj, String propertyName, Object value, Object errors) {
return !list.contains("${obj?.class.name}.${propertyName}".toString())
}
}
...
List blackList = ["Car.carPropertyToExclude", "Details.detailPropertyToExclude"]
grailsWebDataBinder.bind(car, new SimpleMapDataBindingSource(params),
new BlackListener(list:blackList) )
UPD:
Unfortunately the method above does not work with Collection binding.
The problem that SimpleDataBinder.setPropertyValue(...) method loses listener when processing a list.
Not sure if following workaround is good (potentially context initialization required)
but it's possible to register converter for each black list:
import grails.databinding.SimpleDataBinder
import grails.databinding.SimpleMapDataBindingSource
import grails.databinding.converters.ValueConverter
SimpleDataBinder setBlackList(SimpleDataBinder binder, Map<Class,List<String>> blackLists) {
blackLists.each { Class clazz, List<String> blackList ->
def vc = new ValueConverter(){
boolean canConvert(Object value){
return value instanceof Map
}
Object convert(Object value){
def obj = clazz.newInstance()
binder.bind( obj, new SimpleMapDataBindingSource(value), [], blackList )
return obj
}
Class<?> getTargetType(){ clazz }
}
binder.registerConverter(vc)
}
return binder
}
...
Map blackLists = [
(Car.class) : ["carPropertyToExclude"],
(Detail.class) : ["detailPropertyToExclude"]
]
setBlackList(grailsWebDataBinder,blackLists)
...
grailsWebDataBinder.bind(car, new SimpleMapDataBindingSource(params), null,
blackLists[car.getClass()] )
PS: as alternative possible to set grailsWebDataBinder.conversionService...
In a controller you can exclude props from binding by:
def someAction(){
Car car = new Car()
bindData car, params, [exclude: ['carPropertyToExclude', 'details']]
car.details = params.list('details').collect{
bindData new Detail(), [exclude: ['detailPropertyToExclude']]
}
}
You might also want to use the command-objects to represent your form-data.
I have found one solution based on daggett answer. Maybe in greater versions, the bug is fixed or will be fixed. The bug is that when we give the listener as a parameter of bind method for child domains the listener isn't triggered but when we set it as class level listener works. Grails version 3.2.11.
I have created the BlackListener like this:
public class BlackListListener extends DataBindingListenerAdapter {
private final Map<Class<?>, Collection<String>> blackList;
public BlackListListener(Map<Class<?>, Collection<String>> blackList) {
this.blackList = blackList;
}
public Boolean beforeBinding(Object obj, String propertyName, Object value, Object errors) {
Boolean result = Boolean.TRUE;
Collection<String> list = blackList.get(obj.getClass());
if (CollectionUtils.isNotEmpty(list)) {
result = !list.contains(propertyName);
}
return result;
}
}
Then I make my own grailsWebDatabinder bean as prototype:
<bean id="webDataBinder" class="grails.web.databinding.GrailsWebDataBinder" c:_0-ref="grailsApplication"
scope="prototype"/>
<bean id="carBinder" class="CarDataBinder" c:_0-ref="webDataBinder"/>
and then when I want to use data binder I inject the webDataBinder and init listener:
public CarDataBinder(GrailsWebDataBinder grailsWebDataBinder) {
this.grailsWebDataBinder = grailsWebDataBinder;
DataBindingListener blackListListener = new BlackListListener(
ImmutableMap.of(
Car.class, ImmutableSet.of("carPropertyToExclude"),
Detail.class, ImmutableSet.of("detailPropertyToExclude")
)
);
grailsWebDataBinder.setDataBindingListeners(blackListListener);
}
and then:
void bindData(Car car, Map<?, ?> params) {
grailsWebDataBinder.bind(car, new SimpleMapDataBindingSource(params));
}
If there are better ways you can post.
Here Cycle is a domain class
class Cycle {
int lenght = 42
String[] monitor = new String[length]
static mapping = {
monitor defaultValue:"defaultstrval(length)"
}
def defaultstrval(int length)
{
String[] defaultval =new String[length]
for(int i=0;i<length;i++)
{
defaultval[i]=","
}
return defaultval
}
}
Is Domain class only accept sql function.I really need help with good example.
Rather than using the mapping closure to call your function you can simply call the function from your variable assignment like so
String[] monitor = defaultstravel(length)
The code below used to work under the JAXB implementation used by JDK 1.7, but now under JDK 1.8 it's broken. In the code below you will find the key change that seems to make it work in 1.8. The "fix" under 1.8 is not really a fix because it's bad practice to expose internal collections for direct modification by the outside world. I want to control access to the internal list through my class and I don't want to complicate things by making observable collections and listening to them. This is not acceptable.
Is there any way to get my original code to work under the JAXB of JD 1.8?
#XmlElementWrapper(name = "Wrap")
#XmlElement(name = "Item", required = true)
public synchronized void setList(List<CustomObject> values) {
list.clear();
list.addAll(values);
}
public synchronized List<CustomObject> getList() {
// return new ArrayList(list); // this was the original code that worked under 1.7
return list; //this is the only thing that works under 1.8
}
After more analysis, the problem seems to be coming from JAXB not calling the setter method for collections anymore (it used to under JDK 1.7). Now under JDK 1.8, it calls the getter and modifies the collection directly. This poses several problems:
1-forces the user to expose an internal collection to the outside world for free modification (bad practice)
2-doesn't allow the user to do any custom code when the list changes (such as what you could do if the setter was called). It might be possible to make an observable collection and listen to it, but this is a much more complicated workaround than just calling the setter method.
Background
When a collection property is mapped in JAXB it first checks the getter to see if the collection property has been pre-initialized. In the example below I want to have my property exposed as List<String>, but have the backing implementation be a LinkedList ready to hold 1000 items.
private List<String> foos = new LinkedList<String>(1000);
#XmlElement(name="foo")
public List<String> getFoos() {
return foos;
}
Why Your Code Used to Work
If you previously had JAXB call the setter on a property mapped to a collection that returned a non-null response from the getter, then there was a bug in that JAXB implementation. Your code should not have worked in the previous version either.
How to Get the Setter Called
To have the setter called you just need to have your getter return null, on a new instance of the object. Your code could look something like:
import java.util.*;
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "Foo")
public class Foo {
private List<CustomObject> list = null;
#XmlElementWrapper(name = "Wrap")
#XmlElement(name = "Item", required = true)
public synchronized void setList(List<CustomObject> values) {
if (null == list) {
list = new ArrayList<CustomObject>();
} else {
list.clear();
}
list.addAll(values);
}
public synchronized List<CustomObject> getList() {
if (null == list) {
return null;
}
return new ArrayList(list);
}
}
UPDATE
If you don't need to perform any logic on the List returned from JAXB's unmarshalling then using field access may be an acceptable solution.
#XmlRootElement(name = "Foo")
#XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
#XmlElementWrapper(name = "Wrap")
#XmlElement(name = "Item", required = true)
private List<CustomObject> list = null;
public synchronized void setList(List<CustomObject> values) {
if(null == list) {
list = new ArrayList<CustomObject>();
} else {
list.clear();
}
list.addAll(values);
}
public synchronized List<CustomObject> getList() {
return new ArrayList(list);
}
}
I have a class
class Account extends Stuff{
String name;
newObject(){
return new Account();
}
}
inside the Stuff class I have a method
//generates list of objects of the same type
//as given object and fills attribute
generateObjectsFromExisting(names)
{
List list = new List();
InstanceMirror instanceMirror = reflect(this);
Symbol formatSymbol = new Symbol("newObject");
for(var name in names){
//calles newObject function from this and returns a new object
var newInstanceObject = instanceMirror.invoke(formatSymbol, []);
Symbol symbol = new Symbol("name");
InstanceMirror field = newInstanceObject.setField(symbol,name);
list.add(newInstanceObject.reflectee)
}
return list;
}
so when writing
main(){
var account = new Account();
List accounts = new List();
accounts = account.generateObjectsFromExisting(['tim','tom']);
print(account.name) // returns null
print(accounts[0].name) // returns tim
print(accounts[1].name) // returns tom
}
the problems with this way are
1 'generateObjectsFromExisting()' is on the 'account' object and not on Account
2 I have to manually add the "newObject" Method to every single class I implement.
I would prefer a static Method like 'Account.generateObjectsFromExisting()'
but how to to access 'this' (since its not available in static)
so I can say "this.new()" or something equivalent to "new Account();" eg "new this();"
and therefor be able to only have one 'newObject' function inside Stuff or maybe wont need it at all.
so now my code would look like this
class Account extends Stuff{
String name;
}
in Stuff
static generateObjectsFromExisting(names)
{
List list = new List();
for(var name in names){
var object = new this();
object.name = name;
list.add(object)
}
return list;
}
in main
main(){
// returns list of Accounts filled with names
accounts = Account.generateObjectsFromExisting(['tim','tom']);
print(accounts[0].name) // returns tim
print(accounts[1].name) // returns tom
}
if you can show me a way to access the Class to do something like this.new(); or new this(); then obviously the class 'Account' needs to be accessed and not the extended 'Stuff'
if the 'this' approach is not possible, then maybe you can show me a way how to access the Class from within an already existing object
like
generateObjectsFromExisting(names)
{
List list = new List();
var class = this.class;
var newObject = class.new():
...
}
or is my current approach the only solution. .. hope not :)
thank you
There are two ways I can think of at the moment. But both of them are pretty close to your initial solution as they both use reflection..
The non-static solution:
class Stuff {
generateObjectsFromExisting(List<String> names) {
var cm = reflectClass(this.runtimeType);
return names.map((name) {
var newInstance = cm.newInstance(const Symbol(''), []).reflectee;
newInstance.name = name;
return newInstance;
}).toList();
}
}
The static solution:
class Stuff {
static generateObjectsFromExisting(type, List<String> names) {
var cm = reflectClass(type);
return names.map((name) {
var newInstance = cm.newInstance(const Symbol(''), []).reflectee;
newInstance.name = name;
return newInstance;
}).toList();
}
}
You would call the static solution like this:
var accounts = Stuff.generateObjectsFromExisting(Account, ['tim', 'tom']);
There might be another solution involving factory constructors but can't think of any right now. Also, this code would easily break when you get another subclass of Stuff that does not have a name attribute. I don't know if you really intended on putting that attribute on Account instead of Stuff.
Also answering you 'Class'-Question. There is no class in Dart, there is only the Type and to get it you can do:
Type type1 = Account;
Type type2 = account.runtimeType;
But the Type doesn't have any methods you could use to create a new instance.
I am using jena framework to process my owl ontology.
I want to write a method which can find the super class it belongs which is just under the Thing class.
Four example, if there are 5 level hierarchy, lets say first level is Thing, second level is secondAncestor, third level is ThirdAncestor and so on. If I pass a class FifthAncestor, I want to return SecondAncestor because Thing does not make any sense. If I pass ThirdAncestor, I want to return SecondAncestor. In other words, most general class it belongs to but not the top one (Thing).
Method one
This will depend on your model having a reasoner, because owl:Thing isn't normally asserted into a model, and so won't be present in a model with no reasoner. Given that, then:
OntModel m = ... your OntModel ...;
OntClass thing = m.getOntClass( OWL.Thing.getURI() );
for (Iterator<OntClass> i = thing.listSubClasses(true); i.hasNext(); ) {
OntClass hierarchyRoot = i.next();
....
}
Note the use of the flag direct = true in the listSubClasses() call.
Method two
Does not require a reasoner.
for (Iterator<OntClass> i = m.listHierarchyRootClasses(); i.hasNext(); ) {
OntClass hierarchyRoot = i.next();
....
}
Note that this method will return the root classes, even if they are anonymous resources representing a class expression. For UI purposes, this often isn't what you want (it's hard to display a bNode in a meaningful way to a user). In this case, use OntTools.namedHierarchyRoots instead.
Update
I now understand that Alan wants the root classes that are parents of a particular class, whereas namedHierarchyRoots will list all of the root classes of the class hierarchy. Note that, in general, a class may have zero, one or many named-superclasses between it and Thing.
Anyway, here's how I would solve this. Again, this solution assumes the model is not using a reasoner. With a reasoner, it would be much easier:
private boolean hasSubClassTransitive( OntClass parent, OntClass child ) {
return OntTools.findShortestPath( child.getOntModel(), child, parent,
new OntTools.PredicateFilter( RDFS.subClassOf ) ) != null;
}
public List<OntClass> namedRootsOf( OntClass c ) {
List<OntClass> cRoots = new ArrayList<OntClass>();
for (OntClass root: OntTools.namedHierarchyRoots( c.getOntModel() )) {
if (hasSubClassTransitive( root, c )) {
cRoots.add( root );
}
}
return cRoots;
}
I find solution in following way without using reasoner. It is not perfect solution but it works. This solution also solves problem, if you get unnamed (anonymous) class as super class.
First I created an array which stores top level class names.
A simple method which searches in my created array, if the passed parameter is a top class.
public Boolean IsTopClass(String ontologyClass)
{
//NS is URI of ontology
String onClass=ontologyClass.replace(NS, "");
for(String oClass: topLevelClassList)
{
if(oClass.equalsIgnoreCase(onClass))
return true;
}
return false;
}
Then the main method which finds most general class under thing:
public String FindSuperClassUnderThing(OntClass subClass)
{
OntClass prevSubClass=subClass;
OntClass prevprevSubClass=null;
String topClass="";
String supClass=subClass.toString();
ExtendedIterator<OntClass> superClassList=null;
while(!this.IsTopClass(topClass))
{
prevprevSubClass=prevSubClass;
prevSubClass=prevSubClass.getSuperClass();
//if returned class is a anonymous class (not a named one)
//get list of superclasses and check if there is a topclass
//inside the super class list
if(!prevSubClass.toString().startsWith(NS))
{
prevSubClass=prevprevSubClass;
superClassList= prevSubClass.listSuperClasses();
while(superClassList.hasNext())
{
OntClass OntClassFromList= superClassList.next();
if(this.IsTopClass(OntClassFromList.toString()))
{
topClass= OntClassFromList.toString();
}
}
}
else
{
if (this.IsTopClass(prevSubClass.toString()))
{
topClass= prevSubClass.toString();
}
}
}
return topClass;
}