/******************************************************************************* * Copyright (c) 2009, 2010 Fraunhofer IWU and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Fraunhofer IWU - initial API and implementation *******************************************************************************/ package net.enilink.komma.em.concepts; import net.enilink.commons.iterator.IExtendedIterator; import net.enilink.composition.traits.Behaviour; import net.enilink.komma.core.IQuery; import net.enilink.komma.core.IReference; import net.enilink.komma.core.IResultDescriptor; import net.enilink.komma.core.KommaException; import net.enilink.komma.core.URI; import net.enilink.komma.em.results.ResultDescriptor; import net.enilink.vocab.komma.KOMMA; import net.enilink.vocab.owl.OWL; import net.enilink.vocab.rdfs.RDFS; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class ClassSupport extends BehaviorBase implements IClass, Behaviour<IClass> { private static Logger log = LoggerFactory.getLogger(ClassSupport.class); private final String SELECT_DIRECT_SUBCLASSES(boolean named) { StringBuilder sb = new StringBuilder(PREFIX); sb.append("SELECT ?subClass WHERE { "); // support stores that don't draw the inferences // (someClass rdfs:subClassOf rdfs:Resource) and (someClass // rdfs:subClassOf owl:Thing) if (RDFS.TYPE_RESOURCE.equals(this) || OWL.TYPE_THING.equals(this)) { sb.append("{ ?subClass a ") .append(RDFS.TYPE_RESOURCE.equals(this) ? "rdfs:Class" : "owl:Class").append(" . "); sb.append("MINUS { ?subClass rdfs:subClassOf ?someSuperClass . { ?someSuperClass a rdfs:Class } UNION { ?someSuperClass a owl:Class } ") .append("FILTER (isIRI(?someSuperClass) && ?someSuperClass != ?subClass && ?someSuperClass != owl:Thing && ?someSuperClass != rdfs:Resource) } }"); sb.append(" UNION { ?subClass rdfs:subClassOf ?superClass }"); } else { sb.append("?subClass rdfs:subClassOf ?superClass . "); } sb.append("FILTER NOT EXISTS {") .append("?subClass rdfs:subClassOf ?otherSuperClass . ") .append("?otherSuperClass rdfs:subClassOf ?superClass . ") .append("FILTER (") .append(named ? "isIRI(?otherSuperClass) && " : "") .append("?subClass != ?otherSuperClass && ?superClass != ?otherSuperClass)") .append("}") .append(" FILTER (" + (named ? "isIRI(?subClass) && " : "")) .append("?subClass != ?superClass && ?subClass != owl:Nothing)" + "}").append("ORDER BY ?subClass"); return sb.toString(); }; private final String SELECT_SUBCLASSES(boolean named) { return PREFIX + "SELECT DISTINCT ?subClass WHERE { " + ((OWL.TYPE_THING.equals(this)) ? "?subClass a owl:Class . " // : "?subClass rdfs:subClassOf ?superClass . " // ) + "FILTER (?subClass != ?superClass" + (named ? " && isIRI(?subClass)" : "") + ") } ORDER BY ?subClass"; }; private static final String SELECT_LEAF_SUBCLASSES(boolean named) { return PREFIX + "SELECT DISTINCT ?subClass WHERE { " + "?subClass rdfs:subClassOf* ?superClass . OPTIONAL {" + "?otherSubClass rdfs:subClassOf ?subClass . " + "FILTER (?subClass != ?otherSubClass)" + "} FILTER (" + (named ? "isIRI(?subClass) && " : "") + "!bound(?otherSubClass)) } ORDER BY ?subClass"; }; private static final String SELECT_DIRECT_SUPERCLASSES(boolean named) { return PREFIX + "SELECT DISTINCT ?superClass " + "WHERE { " + "?subClass rdfs:subClassOf ?superClass . " + "FILTER NOT EXISTS { ?superClass a owl:Restriction } " + "FILTER NOT EXISTS {" + "?subClass rdfs:subClassOf ?otherSuperClass . " + "?otherSuperClass rdfs:subClassOf ?superClass . " + "FILTER (?subClass != ?otherSuperClass && ?superClass != ?otherSuperClass" + (named ? " && isIRI(?otherSuperClass)" : "") + ")" + "} FILTER (?subClass != ?superClass" + (named ? "&& isIRI(?superClass)" : "") + ") } ORDER BY ?superClass"; }; private static final String SELECT_SUPERCLASSES(boolean named) { return PREFIX + "SELECT DISTINCT ?superClass " + "WHERE { " + "?subClass rdfs:subClassOf ?superClass . " + "FILTER NOT EXISTS {?superClass a owl:Restriction}" + "FILTER (?subClass != ?superClass" + (named ? "&& isIRI(?subClass)" : "") + ") } ORDER BY ?superClass"; } private static final String SELECT_INSTANCES = PREFIX + "SELECT DISTINCT ?instance " + "WHERE { " + "?instance a ?class ." + "}"; private static final String HAS_SUBCLASSES(boolean named) { return PREFIX + "ASK { " + "?subClass rdfs:subClassOf ?superClass . " + "FILTER (" + (named ? "isIRI(?subClass) && " : "") + "?subClass != ?superClass && ?subClass != owl:Nothing)}"; } private static final String SELECT_DECLARED_PROPERTIES = PREFIX + "SELECT DISTINCT ?property " + "WHERE { " + "?property rdfs:domain ?class ." + "} ORDER BY ?property"; private static final String HAS_DECLARED_PROPERTIES = PREFIX + "ASK { " + "?property rdfs:domain ?class ." + "}"; public static final IResultDescriptor<?> HAS_NAMED_SUBCLASSES_DESC() { return new ResultDescriptor<Object>(HAS_SUBCLASSES(true), "komma:hasNamedSubClasses", "subClass", "superClass"); } public static final IResultDescriptor<?> DIRECT_NAMED_SUPERCLASSES_DESC() { return new ResultDescriptor<Object>(SELECT_DIRECT_SUPERCLASSES(true), "komma:directNamedSuperClasses", "superClass", "subClass"); } public IExtendedIterator<IResource> getInstances() { IQuery<?> query = getEntityManager().createQuery(SELECT_INSTANCES); query.setParameter("class", this); return query.evaluate(IResource.class); } public IExtendedIterator<IReference> getInstancesAsReferences() { IQuery<?> query = getEntityManager().createQuery(SELECT_INSTANCES); query.setParameter("class", this); return query.evaluateRestricted(IReference.class); } @Override public IExtendedIterator<IClass> getDirectNamedSubClasses() { // [PERFORMANCE] direct named subclasses are retrieved without inference return getSubClasses(true, false, true); } @Override public IExtendedIterator<IClass> getNamedSubClasses() { return getSubClasses(false, true, true); } @Override public IExtendedIterator<IClass> getSubClasses(boolean direct, boolean includeInferred) { return getSubClasses(direct, includeInferred, false); } protected IExtendedIterator<IClass> getSubClasses(boolean direct, boolean includeInferred, boolean named) { String queryString; if (direct) { queryString = SELECT_DIRECT_SUBCLASSES(named); } else { queryString = SELECT_SUBCLASSES(named); } if (named) { queryString = new ResultDescriptor<IClass>(queryString) // .prefetch(DIRECT_NAMED_SUPERCLASSES_DESC()).prefetchTypes() .prefetch(HAS_NAMED_SUBCLASSES_DESC()).// prefetch(ResourceSupport.DIRECT_NAMED_CLASSES_DESC()).// toQueryString(); } IQuery<?> query = getEntityManager().createQuery(queryString, includeInferred); query.setParameter("superClass", this); return query.evaluate(IClass.class); } @Override public Boolean hasNamedSubClasses() { return getEntityManager() .createQuery(HAS_NAMED_SUBCLASSES_DESC().toQueryString()) .setParameter("superClass", this).getBooleanResult(); } @Override public IExtendedIterator<IClass> getNamedLeafSubClasses( boolean includeInferred) { return getLeafSubClasses(includeInferred, true); } @Override public IExtendedIterator<IClass> getLeafSubClasses(boolean includeInferred) { return getLeafSubClasses(includeInferred, false); } protected IExtendedIterator<IClass> getLeafSubClasses( boolean includeInferred, boolean named) { IQuery<?> query = getEntityManager().createQuery( SELECT_LEAF_SUBCLASSES(named), includeInferred); query.setParameter("superClass", getBehaviourDelegate()); return query.evaluate(IClass.class); } @Override public IExtendedIterator<IClass> getDirectNamedSuperClasses() { log.info("Get super classes for {}", getBehaviourDelegate()); // [PERFORMANCE] direct named super-classes are retrieved without // inference return getEntityManager() .createQuery(DIRECT_NAMED_SUPERCLASSES_DESC().toQueryString(), false).setParameter("subClass", getBehaviourDelegate()) .evaluate(IClass.class); } @Override public IExtendedIterator<IClass> getNamedSuperClasses() { return getSuperClasses(false, true, true); } @Override public IExtendedIterator<IClass> getSuperClasses(boolean direct, boolean includeInferred) { return getSuperClasses(direct, includeInferred, false); } protected IExtendedIterator<IClass> getSuperClasses(boolean direct, boolean includeInferred, boolean named) { if (direct && named) { return getBehaviourDelegate().getDirectNamedSuperClasses(); } IQuery<?> query = getEntityManager().createQuery( direct ? SELECT_DIRECT_SUPERCLASSES(named) : SELECT_SUPERCLASSES(named), includeInferred); query.setParameter("subClass", getBehaviourDelegate()); return query.evaluate(IClass.class); } @Override public boolean hasNamedSubClasses(boolean includeInferred) { return hasSubClasses(includeInferred, true); } @Override public boolean hasSubClasses(boolean includeInferred) { return hasSubClasses(includeInferred, false); } protected boolean hasSubClasses(boolean includeInferred, boolean named) { if (named) { // use cacheable method return getBehaviourDelegate().hasNamedSubClasses(); } try { IQuery<?> query = getEntityManager().createQuery( HAS_SUBCLASSES(named), includeInferred); query.setParameter("superClass", this); return query.getBooleanResult(); } catch (Exception e) { throw new KommaException(e); } } public boolean hasDeclaredProperties(boolean includeInferred) { try { IQuery<?> query = getEntityManager().createQuery( HAS_DECLARED_PROPERTIES, includeInferred); query.setParameter("class", this); return query.getBooleanResult(); } catch (Exception e) { throw new KommaException(e); } } @SuppressWarnings("unchecked") public IExtendedIterator<IProperty> getDeclaredProperties( boolean includeInferred) { IQuery<?> query = getEntityManager().createQuery( SELECT_DECLARED_PROPERTIES, includeInferred); query.setParameter("class", getBehaviourDelegate()); return (IExtendedIterator<IProperty>) query.evaluate(); } @Override public IResource newInstance() { return newInstance(null); } @Override public IResource newInstance(URI uri) { if (uri == null) { return (IResource) getEntityManager() .create(getBehaviourDelegate()); } return (IResource) getEntityManager().createNamed(uri, getBehaviourDelegate()); } @Override public boolean isAbstract() { return getAsSet(KOMMA.PROPERTY_ISABSTRACT).contains(Boolean.TRUE); } }