Finding The Super Class of a class just before Top Class with Jena - jena

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;
}

Related

Inherited grails domain classes missing dynamic properties

I'm having a problem where the related table id fields return 'null' from my domain objects when using inheritance. Here is an example:
In /src/groovy/
BaseClass1.groovy
class BaseClass1 {
Long id
static mapping = {
tablePerConcreteClass true
}
}
BaseClass2.groovy
class BaseClass2 extends BaseClass1 {
String someOtherProperty
static constraints = {
someOtherProperty(maxSize:200)
}
static mapping = BaseClass1.mapping
}
In /grails-app/domain
ParentClass.groovy
class ParentClass extends BaseClass2 {
ChildClass myChild
static mapping = BaseClass2.mapping << {
version false
}
}
ChildClass.groovy
class ChildClass extends BaseClass1 {
String property
static mapping = BaseClass1.mapping
}
The problem appears here:
SomeotherCode.groovy
print parentClassInstance.myChild.id // returns the value
print parentClassInstance.myChildId // returns null
Any ideas what might be going on to get those dynamic properties to break like this?
After debugging into the get(AssociationName)Id source, I found the following:
The handler for this is:
GrailsDomainConfigurationUtil.getAssociationIdentifier(Object target, String propertyName,
GrailsDomainClass referencedDomainClass) {
String getterName = GrailsClassUtils.getGetterName(propertyName);
try {
Method m = target.getClass().getMethod(getterName, EMPTY_CLASS_ARRAY);
Object value = m.invoke(target);
if (value != null && referencedDomainClass != null) {
String identifierGetter = GrailsClassUtils.getGetterName(referencedDomainClass.getIdentifier().getName());
m = value.getClass().getDeclaredMethod(identifierGetter, EMPTY_CLASS_ARRAY);
return (Serializable)m.invoke(value);
}
}
catch (NoSuchMethodException e) {
// ignore
}
catch (IllegalAccessException e) {
// ignore
}
catch (InvocationTargetException e) {
// ignore
}
return null;
}
It threw an exception on the related class (value.getClass().getDeclaredMethod), saying NoSuchMethod for the method getId(). I was unable to remove the id declaration from the base class without Grails complaining that an identifier column was required. I tried marking id as public and it also complained that it wasn't there. So, I tried this
BaseClass {
Long id
public Long getId() { return this.#id }
}
and things worked on some classes, but not on others.
When I removed the ID declaration, I go an error: "Identity property not found, but required in domain class". On a whim, I tried adding #Entity to the concrete classes and viola! everything started working.
class BaseClass {
//Don't declare id!
}
#Entity
class ParentClass {}
#Entity
class ChildClass {}
I still think it is a grails bug that it needs to be added, but at least it is easy enough to work around.
I'm not sure why you are seeing this behavior, but I'm also not sure why you are doing some of the things you are doing here. Why have a domain class extend a POGO? Domains, Controllers, and Services are heavily managed by the Grails machinery, which probably was not designed for this sort of use. Specifically, I believe Grails builds the dynamic property getters for the GrailsDomainProperty(s) of GrailsDomainClass(es), not POGO's. In this case, you have an explicitly declared id field in BaseClass1 that is not a GrailsDomainProperty. I suspect that this POGO id property is not picked up by the Grails machinery that creates the dynamic property getters for Domains.
You might try putting BaseClass1/2 in /grails-app/domain, perhaps making them abstract if you don't want them instantiated, then extending them as you are and seeing if you observe the behavior you want.

Customize sorting in criteria

I found grails criteria and want to customize sorting options.
E.g. I have domain Book and I want to make some criteria:
Book.createCriteria().list {
//some code like ilike('name', 'book')
...
order(params.sort, params.order)
}
I want to make specific sorting rule, e.g. by name.trim().
How can I do this?
Based on a solution provided here, by extending the hirbernate Order class, you can customize it to accept functions and use it with createCriteria.
I wont be surprised, if there is a nicer and easier approach since this source is pretty old and also Grails is cooler than this :D
First you need a class extending Hibernate Order:
Originally by:spostelnicu
public class OrderBySqlFormula extends Order {
private String sqlFormula;
protected OrderBySqlFormula(String sqlFormula) {
super(sqlFormula, true);
this.sqlFormula = sqlFormula;
}
public String toString() {
return sqlFormula;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return sqlFormula;
}
public static Order sqlFormula(String sqlFormula) {
return new OrderBySqlFormula(sqlFormula);
}
}
Then you can pass instance of this class to your createCriteria:
def ls = Domain.createCriteria().list {
order OrderBySqlFormula.sqlFormula("TRIM(name)")
}
Note1: You can pass any formula to sqlFormula as long as the underlying database accepts it.
Note2: Using such approach might cause migration challenges.
Hope it helps

OntModel interface has no listHierarchyRootProperties method

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);
}
}
}

How to access other filter values inside of a custom addXXXColumnCriteria?

I have a request to create a form filter that has two fields, one a freeform text
and the other a select. The value in the select will determine how to handle the value of the text is turned into a criteria.
I can create a custom addXXXColumnCriteria for either field, but how can I access the other field from within this function?
I suggest you not to use de addXXXColumnCriteria, but overwrite the FormFilter doBuildCriteria (Propel) or doBuildQuery(Doctrine) methods.
I have never used Propel, but I guess that works as good as for Doctrine.
For example:
class yourPropelFormFilter extends anyKindOfSfFormFilterPropel {
public function doBuildCriteria(array $values) {
$criteria = parent::doBuildCriteria($values);
// ... change the criteria behaviour with the $values array (do some print_r to $values to see how the data array is formatted)
return $criteria;
}
}
For Doctrine (remember to use the getRootAlias query method):
class yourDoctrineFormFilter extends anyKindOfSfFormFilterDoctrine {
public function doBuildQuery(array $values) {
$q = parent::doBuildQuery($values);
$rootAlias = $q->getRootAlias();
if(...) {
$q->innerJoin($rootAlias.'.RelationX rx')
->addWhere('rx.value = ?',$values['...']);
}
return $q;
}
}
Please, remember to return the criteria/query modified object!

Set Inner Dependency by Type using Structuremap

I have a structuremap configuration that has me scratching my head. I have a concrete class that requires a interfaced ui element which requires an interfaced validation class. I want the outer concrete class to get the default ui element, but get a concrete-class-specific validation object. Something like this:
class MyView
{
IPrompt prompt
}
class GenericPrompt : IPrompt
{
IValidator validator
}
class MyValidator : IValidator
{
bool Validate() {}
}
How can I configure structuremap with the Registry DSL to only use MyValidator when creating dependencies for MyView. (And assumedly using BobsValidator when creating dependencies for BobsView)
Are you getting MyView (and BobsView) from the container? Can we assume that they will all take an instance of IPrompt?
One approach would be to register all of your validators with a name that matches the names of your view. You could implement your own type scanner that just removes the Validator suffix:
public class ValidatorScanner : ITypeScanner
{
public void Process(Type type, PluginGraph graph)
{
if (!typeof (IValidator).IsAssignableFrom(type)) return;
var validatorName = type.Name.Replace("Validator", "");
graph.AddType(typeof(IValidator), type, validatorName);
}
}
Now, if you assume an IPrompt will always be requested by a View that follows that naming convention, your registry could look like:
public class ValidatorRegistry : Registry
{
public ValidatorRegistry()
{
Scan(scan =>
{
scan.TheCallingAssembly();
scan.With<ValidatorScanner>();
});
ForRequestedType<IPrompt>().TheDefault.Is.ConstructedBy(ctx =>
{
var viewName = ctx.Root.RequestedType.Name.Replace("View", "");
ctx.RegisterDefault(typeof(IValidator), ctx.GetInstance<IValidator>(viewName));
return ctx.GetInstance<GenericPrompt>();
});
}
}
To retrieve your view with the appropriate validator, you would have to request the concrete type:
var view = container.GetInstance<MyView>();
Note that this will only work if you are retrieving your view with a direct call to the container (service location), since it depends on the "Root.RequestedType". Depending on how you plan to get your views, you might be able to walk up the BuildStack looking for a View (instead of assuming it is always Root).

Resources