All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.konig.core.OwlReasoner Maven / Gradle / Ivy

There is a newer version: 2.11.0
Show newest version
package io.konig.core;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

/*
 * #%L
 * konig-core
 * %%
 * Copyright (C) 2015 - 2016 Gregory McFall
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */


import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.openrdf.model.Resource;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.vocabulary.GEO;
import org.openrdf.model.vocabulary.OWL;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.model.vocabulary.XMLSchema;

import io.konig.core.impl.RdfUtil;
import io.konig.core.vocab.Konig;
import io.konig.core.vocab.OwlVocab;
import io.konig.core.vocab.Schema;
import io.konig.core.vocab.XSD;
import io.konig.shacl.PropertyConstraint;
import io.konig.shacl.Shape;
import io.konig.shacl.ShapeManager;

public class OwlReasoner {
	
	private Graph graph;
	private Map equivalentClassMap;
	private Map datatypeMap;
	private boolean inferredClassesFromSubclass;
	
	public OwlReasoner(Graph graph) {
		this.graph = graph;
	}
	
	public Graph getGraph() {
		return graph;
	}
	
	public Resource getRange(URI predicate) {
		Vertex v = graph.getVertex(predicate);
		return v==null ? null : v.getResource(RDFS.RANGE);
	}
	
	public Resource getDomain(URI predicate) {

		Vertex v = graph.getVertex(predicate);
		return v==null ? null : v.getResource(RDFS.DOMAIN);
	}
	
	public String friendlyName(Resource subject) {
		if (subject != null) {
			Vertex v = graph.getVertex(subject);
			if (v != null) {
				return friendlyName(v);
			}
		}
		return null;
	}

	public Set allNamedIndividuals() {
		Set set = new HashSet<>();
	
		addSubclasses(set, Schema.Enumeration);
		addSubclasses(set, OwlVocab.NamedIndividual);
		
		Set result = new HashSet<>();
		for (Vertex v : set) {
			Resource id = v.getId();
			if (id instanceof URI) {
				addAllInstances(result, (URI)id);
			}
		}
		
		return result;
	}
	
	private void addSubclasses(Set set, URI classId) {
		Vertex v = graph.getVertex(classId);
		if (v != null) {
			set.add(v);
			set.addAll(subClassVertices(classId));
		}
		
	}

	public Set allClassIds() {
		Set set = new HashSet<>();
		for (Vertex v : owlClassList()) {
			if (v.getId() instanceof URI) {
				set.add((URI) v.getId());
			}
		}
		return set;
	}
	
	public Set allRdfOwlAndShaclProperties(ShapeManager shapeManager) {
		Set rdfOwl = allRdfAndOwlProperties();
		
		Set result = new HashSet<>();
		for (Vertex v : rdfOwl) {
			if (v.getId() instanceof URI) {
				result.add((URI) v.getId());
			}
		}
		
		if (shapeManager != null) {
			for (Shape shape : shapeManager.listShapes()) {
				for (PropertyConstraint p : shape.getProperty()) {
					URI predicate = p.getPredicate();
					if (predicate != null) {
						result.add(predicate);
					}
				}
			}
		}
		
		return result;
	}
	
	/**
	 * Get the set of vertices that are declared in the Graph as RDF Properties (including terms from the OWL vocabulary).
	 */
	public Set allRdfAndOwlProperties() {
		Set set = new HashSet<>();
		addAllInstances(set, RDF.PROPERTY);
		addAllInstances(set, OWL.FUNCTIONALPROPERTY);
		addAllInstances(set, OWL.DATATYPEPROPERTY);
		addAllInstances(set, OWL.OBJECTPROPERTY);
		addAllInstances(set, OWL.ANNOTATIONPROPERTY);
		addAllInstances(set, OWL.DEPRECATEDPROPERTY);
		addAllInstances(set, OWL.EQUIVALENTPROPERTY);
		addAllInstances(set, OWL.INVERSEFUNCTIONALPROPERTY);
		addAllInstances(set, OWL.ONTOLOGYPROPERTY);
		addAllInstances(set, OWL.SYMMETRICPROPERTY);
		addAllInstances(set, OWL.TRANSITIVEPROPERTY);
		return set;
	}
	
	private void addAllInstances(Set set, URI entityType) {
		Vertex v = graph.getVertex(entityType);
		if (v != null) {
			set.addAll(v.asTraversal().in(RDF.TYPE).toVertexList());
		}
	}
	
	public String friendlyName(Vertex subject) {
		String name = stringValue(subject, Schema.name, RDFS.LABEL);
		if (name == null) {
			name = subject.getId() instanceof URI ?
					((URI)subject.getId()).getLocalName() : subject.getId().stringValue();
		}
		
		return name;
	}
	
	public String stringValue(Vertex subject, URI...predicate) {
		for (URI p : predicate) {
			Value value = subject.getValue(p);
			if (value != null) {
				return value.stringValue();
			}
		}
		return null;
	}

	public List owlClassList() {
		return graph.v(OWL.CLASS).in(RDF.TYPE).toVertexList();
	}
	
	public List ontologyList() {
		return graph.v(OWL.ONTOLOGY).in(RDF.TYPE).toVertexList();
	}
	
	public List subClasses(Vertex v) {
		return v.asTraversal().in(RDFS.SUBCLASSOF).toVertexList();
	}
	
	public List subClassVertices(URI classId) {

		return graph.v(classId).in(RDFS.SUBCLASSOF).toVertexList();
	}
	
	public Set subClasses(URI classId) {
		return graph.v(classId).in(RDFS.SUBCLASSOF).toUriSet();
	}
	
	public Set allSubClasses(Vertex v) {
		Set set = new HashSet<>();
		addSubClasses(set, subClasses(v));
		return set;
	}
	
	private void addSubClasses(Set set, List subClasses) {
		for (Vertex v : subClasses) {
			if (!set.contains(v)) {
				set.add(v);
				addSubClasses(set, subClasses(v));
			}
		}
		
	}

	public Set namedSubClasses(Resource typeId) {
		Vertex v = graph.getVertex(typeId);
		if (v == null) {
			return new HashSet();
		}
		return v.asTraversal().in(RDFS.SUBCLASSOF).toUriSet();
	}
	
	public Set allNamedSubClasses(Resource typeId) {
		Vertex v = graph.getVertex(typeId);
		if (v == null) {
			return new HashSet();
		}
		Set result = new HashSet<>();
		Set vertices = allSubClasses(v);
		for (Vertex u : vertices) {
			if (u.getId() instanceof URI) {
				result.add((URI) u.getId());
			}
		}
		return result;
		
	}
	
	

	/**
	 * Ensure that every member within a set of equivalent classes contains 
	 * an owl:equivalentClass property whose value is the preferred class.
	 */
	private void buildEquivalentClasses() {
		if (equivalentClassMap == null) {
			inferClassFromSubclassOf();
			List list = graph.v(OWL.CLASS)
				.union(RDFS.CLASS).union(RDFS.DATATYPE).union(Schema.DataType).union(RDFS.LITERAL)
				.distinct().in(RDF.TYPE).distinct().toVertexList();
			equivalentClassMap = new HashMap<>();
			
			assembleEquivalenceClasses(list, equivalentClassMap);
		}
	}
	
	@SuppressWarnings("unchecked")
	public Set rangeIncludes(URI property) {
		Set result =  graph.v(property).out(RDFS.RANGE).toUriSet();
		Set rest = graph.v(property).out(Schema.rangeIncludes).toUriSet();
		result.addAll(rest);
		
		return result;
	}
	
	public void inferRdfPropertiesFromPropertyConstraints(ShapeManager shapeManager, Graph sink) {
		if (shapeManager == null) {
			return;
		}
		if (sink == null) {
			sink = graph;
		}
		
		
		for (Shape shape : shapeManager.listShapes()) {
			URI targetClass = shape.getTargetClass();
		
			for (PropertyConstraint p : shape.getProperty()) {
				URI predicate = p.getPredicate();
				if (predicate != null) {

					Vertex property = graph.getVertex(predicate);
					URI propertyType = null;
					URI range = null;
					URI domain = null;
					if (property != null) {

						propertyType = property.getURI(RDF.TYPE);
						range = property.getURI(RDFS.RANGE);
						domain = property.getURI(RDFS.RANGE);
						if (domain != null) {
							targetClass = null;
						}
					}
					
					URI datatype =  p.getDatatype();
					if (datatype != null) {
						URI type = propertyType==null ? OWL.DATATYPEPROPERTY : null;
						edge(sink, predicate, RDF.TYPE, type);
						edge(sink, predicate, Schema.domainIncludes, targetClass);
						edge(sink, predicate, Schema.rangeIncludes, datatype);
					} else {
						URI valueClass = range==null ? asIRI(p.getValueClass()) : null;
						URI type = propertyType==null ? OWL.OBJECTPROPERTY : null;
						if (valueClass != null) {
							edge(sink, predicate, RDF.TYPE, type);
							edge(sink, predicate, Schema.domainIncludes, targetClass);
							edge(sink, predicate, Schema.rangeIncludes, valueClass);
						} else {
							Shape valueShape = p.getShape();
							if (valueShape != null) {
								valueClass = valueShape.getTargetClass();
								if (valueClass != null) {
									edge(sink, predicate, RDF.TYPE, type);
									edge(sink, predicate, Schema.domainIncludes, targetClass);
									edge(sink, predicate, Schema.rangeIncludes, valueClass);
								} else {
									edge(sink, predicate, RDF.TYPE, type);
									edge(sink, predicate, Schema.domainIncludes, targetClass);
								}
							} else {
								edge(sink, predicate, RDF.TYPE, type);
								edge(sink, predicate, Schema.domainIncludes, targetClass);
							}
						}
					}
				}
			}
		}
		
	}
	
	private URI asIRI(Resource resource) {
		
		return resource instanceof URI ? (URI) resource : null;
	}

	private void edge(Graph sink, Resource subject, URI predicate, Value object) {
		if (sink!=null && subject!=null && predicate!=null && object!=null) {
			sink.edge(subject, predicate, object);
		}
	}


	private void assembleEquivalenceClasses(List list, Map map) {
		for (Vertex owlClass : list) {
			analyzeEquivalentClasses(owlClass, map);
		}
	}

	/**
	 * Compute the transitive closure of the equivalent classes of the specified owlClass
	 * @param owlClass  The class from which the transitive closure will be computed
	 * @param map A map from the id for an owlClass to the EquivalenceClass to which it belongs.
	 */
	private void analyzeEquivalentClasses(Vertex owlClass, Map map) {
		
		String key = owlClass.getId().stringValue();
		EquivalenceClass e = map.get(key);
		if (e == null) {
			e = new EquivalenceClass();
			map.put(key, e);
			
			addMembers(e, owlClass, map);
		}
		
	}


	private void addMembers(EquivalenceClass e, Vertex owlClass, Map map) {
		
		Set set = e.getMembers();
		set.add(owlClass);
		List list = owlClass.asTraversal().out(OWL.EQUIVALENTCLASS).distinct().toVertexList();
		for (Vertex v : list) {
			String otherKey = v.getId().stringValue();
			EquivalenceClass other = map.get(otherKey);
			
			if (other == null) {
				map.put(otherKey, e);
				set.add(v);
				addMembers(e, v, map);
				
			} else if (other != e) {
				map.put(otherKey, e);
				e.addAll(other);
			}
		}
		
	}


	private static class EquivalenceClass {
		private Set members = new HashSet<>();
		private Vertex preferredEntity;
		private boolean computedPreferredEntity;
		
		public Vertex getPreferredEntity(URI preferredType) throws AmbiguousPreferredClassException {
			if (!computedPreferredEntity) {
				computedPreferredEntity = true;
				
				for (Vertex v : members) {
					if (v.hasProperty(RDF.TYPE, preferredType)) {
						if (preferredEntity == null) {
							preferredEntity = v;
						} else {
							throw new AmbiguousPreferredClassException(members);
						}
					}
				}
				
			}
			
			return preferredEntity;
		}
		
		
		public Set getMembers() {
			return members;
		}
		
		public void addAll(EquivalenceClass other) {
			members.addAll(other.getMembers());
		}
		
		
		
	}


	/**
	 * Identify the preferred class from the set of classes equivalent to a given class.
	 * @param owlClass The given OWL class that may or may not have equivalent classes.
	 * @return If there are classes equivalent to the given owlClass, then return the
	 * member from the set of equivalent classes that contains the kol:isPreferredClass 
	 * with the value 'true'.
	 * @throws AmbiguousPreferredClassException 
	 */
	public Vertex preferredClass(Vertex owlClass) throws AmbiguousPreferredClassException {
		buildEquivalentClasses();
		EquivalenceClass e = equivalentClassMap.get(owlClass.getId().stringValue());
		if (e != null) {
			Vertex result =  e.getPreferredEntity(Konig.PreferredClass);
			if (result != null) {
				owlClass = result;
			}
		}
		
		return owlClass;
	}
	
	public boolean isSubclassOfLiteral(Resource id) {
		return isDatatype(id) || isSubClassOf(id, RDFS.LITERAL);
	}
	
	public boolean isDatatype(Resource id) {
		if (id instanceof URI) {
			URI uri = (URI) id;
			if (
				XMLSchema.NAMESPACE.equals(uri.getNamespace()) ||
				GEO.WKT_LITERAL.equals(id) ||
				RDF.LANGSTRING.equals(id)
			) {
				return true;
			}
		}
		Vertex v = graph.getVertex(id);
		if (v != null) {
			boolean truth = !v.asTraversal().hasValue(RDF.TYPE, RDFS.DATATYPE).toVertexList().isEmpty();
			if (truth) {
				return true;
			}
			// TODO: apply other kinds of inference
		}
		return false;
	}
	

	/**
	 * Compute the least common super datatype between two given datatypes.
	 * @param aType The first class
	 * @param bType The second class
	 * @return The least common super class between the two classes.
	 */
	public Resource leastCommonSuperDatatype(Resource aType, Resource bType) {
		Vertex a = graph.vertex(aType);
		Vertex b = graph.vertex(bType);
		if (RdfUtil.isSubClassOf(a, bType)) {
			return bType;
		}
		if (RdfUtil.isSubClassOf(b, aType)) {
			return aType;
		}
		
		Set set = superClasses(a);
		List stack = b.asTraversal().out(RDFS.SUBCLASSOF).toVertexList();
		for (int i=0; i classes) {
		URI result = null;
		for (URI owlClass : classes) {
			if (result == null) {
				result = owlClass;
			} else {
				result = (URI) leastCommonSuperClass(result, owlClass);
				if (result.equals(OWL.THING)) {
					return OWL.THING;
				}
			}
			
		}
		return result;
	}
	
	/**
	 * Compute the least common super class between two given classes.
	 * @param aClass The first class
	 * @param bClass The second class
	 * @return The least common super class between the two classes.
	 */
	public Resource leastCommonSuperClass(Resource aClass, Resource bClass) {
		
		if (aClass==null) {
			return bClass;
		}
		if (bClass==null) {
			return aClass;
		}
		
		if (aClass.equals(bClass)) {
			return aClass;
		}
		Vertex a = graph.vertex(aClass);
		Vertex b = graph.vertex(bClass);
		if (RdfUtil.isSubClassOf(a, bClass)) {
			return bClass;
		}
		if (RdfUtil.isSubClassOf(b, aClass)) {
			return aClass;
		}
		
		Set set = superClasses(a);
		List stack = b.asTraversal().out(RDFS.SUBCLASSOF).toVertexList();
		for (int i=0; i superClasses(Vertex a) {
		Set set = new HashSet<>();
		List stack = new ArrayList<>();
		stack.addAll(equivalentClasses(a.getId()));
		
		for (int i=0; i next = w.asTraversal().out(RDFS.SUBCLASSOF).toVertexList();
			for (Vertex v : next) {
				Set eq = equivalentClasses(v.getId());
				for (Vertex u : eq) {
					if (!stack.contains(u)) {
						stack.add(u);
						if (u.getId() instanceof URI) {
							set.add(u.getId().stringValue());
						}
					}
				}
			}
		}
		
		return set;
	}
	
	/**
	 * Check whether one type is a subClassOf another.
	 * @param a The identifier for one OWL Class
	 * @param b The identifier for another OWL Class.
	 * @return True if a and b are equal or a is a subClassOf b (or one of b's ancestors).
	 */
	public boolean isSubClassOf(Resource a, Resource b) {
		if (a == null) {
			throw new IllegalArgumentException("Resource must not be null");
		}
		if (a.equals(b)) {
			return true;
		}
		Vertex va = graph.getVertex(a);
		if (va == null) {
			return false;
		}
		return RdfUtil.isSubClassOf(va, b);
	}

	public Set equivalentClasses(Resource owlClass) {
		buildEquivalentClasses();

		EquivalenceClass e = equivalentClassMap.get(owlClass.stringValue());
		if (e == null) {
			Vertex v = graph.vertex(owlClass);
			Set result = new HashSet<>();
			result.add(v);
			return result;
		}
		return e.getMembers();
	}
	
	public Vertex preferredClass(Resource owlClass) throws AmbiguousPreferredClassException {
		return preferredClass(graph.vertex(owlClass));
	}

	public URI preferredClassAsURI(URI owlClass) throws AmbiguousPreferredClassException {
		return (URI) preferredClass(graph.vertex(owlClass)).getId();
	}
	
	public void inferTypeOfSuperClass(Vertex thing) {
		Set typeSet = thing.asTraversal().out(RDF.TYPE).toUriSet();
		
		Set superSet = new HashSet<>();
		for (URI uri : typeSet) {
			getTransitiveClosure(uri, RDFS.SUBCLASSOF, superSet);
		}
		
		for (URI superClass : superSet) {
			graph.edge(thing.getId(), RDF.TYPE, superClass);
		}
		
	}
	
	public void getTransitiveClosure(Resource source, URI predicate, Set sink) {
		Vertex v = graph.getVertex(source);
		if (v != null) {
			Set out = v.outProperty(predicate);
			for (Edge e : out) {
				Value object = e.getObject();
				if (object instanceof URI) {
					URI uri = (URI) object;
					if (!sink.contains(uri)) {
						sink.add(uri);
						getTransitiveClosure(uri, predicate, sink);
					}
				}
			}
		}
	}
	
	public URI mostSpecificType(Iterable collection, URI filter) {
		URI best = null;
		for (URI candidate : collection) {
			
			if (filter != null && !candidate.equals(filter) && !isSubClassOf(candidate, filter)) {
				continue;
			}
			
			if (best == null) {
				best = candidate;
			} else if (isSubClassOf(candidate, best)) {
				best = candidate;
			} 
		}
		
		return best;
	}
	
	public void inferClassesFromShapes(ShapeManager shapeManager, Graph sink) {
		for (Shape shape : shapeManager.listShapes()) {
			URI targetClass = shape.getTargetClass();
			if (targetClass != null) {
				sink.edge(targetClass, RDF.TYPE, OWL.CLASS);
			}
			for (PropertyConstraint p : shape.getProperty()) {
				Resource owlClass = p.getValueClass();
				if (owlClass != null) {
					sink.edge(owlClass, RDF.TYPE, OWL.CLASS);
				}
			}
		}
	}
	
	public void inferClassFromSubclassOf() {
		if (!inferredClassesFromSubclass) {
			inferredClassesFromSubclass = true;
			List list = new ArrayList<>(graph);
			for (Edge e : list) {
				URI predicate = e.getPredicate();
				if (predicate.equals(RDFS.SUBCLASSOF)) {
					graph.edge(e.getSubject(), RDF.TYPE, OWL.CLASS);
					graph.edge((Resource) e.getObject(), RDF.TYPE, OWL.CLASS);
				}
			}
		}
	}
	
	/**
	 * Test whether a given Resource is an instance of a given OWL Class.
	 * This method checks the rdf:type relationship, and infers based on rdfs:subClassOf relationships.
	 * 
	 * @param subject The Resource whose type is to be tested.
	 * @param owlClass The OWL Class to be matched
	 * @return True if the subject is an instance of the specified owlClass and false otherwise.
	 */
	public boolean instanceOf(Resource subject, URI owlClass) {
		Vertex v = graph.getVertex(subject);
		if (v != null) {
			Set typeSet = v.asTraversal().out(RDF.TYPE).toUriSet();
			for (URI type : typeSet) {
				if (type.equals(owlClass)) {
					return true;
				}
			}
			
			Set superTypeSet = new HashSet<>();
			for (URI type : typeSet) {
				getTransitiveClosure(type, RDFS.SUBCLASSOF, superTypeSet);
			}
			
			for (URI superType : superTypeSet) {
				if (superType.equals(owlClass)) {
					return true;
				}
			}
		}
		return false;
	}
	
	public boolean isRealNumber(URI owlClass) {
		return 
				XMLSchema.DECIMAL.equals(owlClass) ||
				XMLSchema.DOUBLE.equals(owlClass) ||
				XMLSchema.FLOAT.equals(owlClass) ||
				Schema.Float.equals(owlClass) ||
				Schema.Number.equals(owlClass);
	}
	
	public boolean isBooleanType(URI owlClass) {
		return
				XMLSchema.BOOLEAN.equals(owlClass) ||
				Schema.Boolean.equals(owlClass);
	}
	
	public boolean isPlainLiteral(URI owlClass) {
		return
				XMLSchema.STRING.equals(owlClass) ||
				Schema.Text.equals(owlClass);
	}
	
	/**
	 * Get the set of all properties that are declared to be the owl:inverseOf
	 * a given property.
	 * @param property  The IRI of the property whose inverse is to be returned.
	 * @return  The set of identifiers for properties that are declared to be the inverse of the given property.
	 */
	public Set inverseOf(URI property) {
		Set result = new HashSet<>();
		
		Set outward = graph.v(property).out(OWL.INVERSEOF).toUriSet();
		result.addAll(outward);
		
		Set inward = graph.v(property).in(OWL.INVERSEOF).toUriSet();
		result.addAll(inward);
		
		return result;
	}
	
	public boolean isInverseFunctionalProperty(URI property) {
		return instanceOf(property, OWL.INVERSEFUNCTIONALPROPERTY);
	}
	
	public boolean isNumericDatatype(URI owlClass) {
		return isIntegerDatatype(owlClass) || isRealNumber(owlClass);
	}
	
	public boolean isIntegerDatatype(URI owlClass) {
		return
				XMLSchema.BYTE.equals(owlClass) ||
				XMLSchema.INT.equals(owlClass) ||
				XMLSchema.INTEGER.equals(owlClass) ||
				XMLSchema.LONG.equals(owlClass) ||
				XMLSchema.NEGATIVE_INTEGER.equals(owlClass) ||
				XMLSchema.NON_NEGATIVE_INTEGER.equals(owlClass) ||
				XMLSchema.NON_POSITIVE_INTEGER.equals(owlClass) ||
				XMLSchema.SHORT.equals(owlClass) ||
				XMLSchema.UNSIGNED_BYTE.equals(owlClass) ||
				XMLSchema.UNSIGNED_INT.equals(owlClass) ||
				XMLSchema.UNSIGNED_LONG.equals(owlClass) ||
				XMLSchema.UNSIGNED_SHORT.equals(owlClass) ||
				Schema.Integer.equals(owlClass);
			
	}
	
	public boolean isEnumerationClass(Resource owlClass) {
		return isSubClassOf(owlClass, Schema.Enumeration);
	}
	
	/**
	 * Check whether a given individual is an instance of a given OWL Class.
	 * @param individual The individual to be checked.
	 * @param owlClass The target OWL Class.
	 * @return True if the individual is an instance of the OWL Class, and false otherwise.
	 */
	public boolean isTypeOf(Resource individual, Resource owlClass) {
		Vertex v = graph.getVertex(individual);
		if (v != null) {
			List typeList = v.asTraversal().out(RDF.TYPE).toVertexList();
			for (Vertex type : typeList) {
				if (type.getId().equals(owlClass)) {
					return true;
				}
			}
			
			for (Vertex type : typeList) {
				Resource typeId = type.getId();
				if (isSubClassOf(typeId, owlClass)) {
					return true;
				}
			}
		}
		return false;
	}

	public DatatypeRestriction datatypeRestriction(URI datatype) {
		getDatatypeMap();
		DatatypeRestriction result = datatypeMap.get(datatype.stringValue());
		if (result == null) {
			result = createDatatypeRestriction(datatype);
			datatypeMap.put(datatype.stringValue(), result);
		}
		return result;
	}
	
	private DatatypeRestriction createDatatypeRestriction(URI datatype) {
		
		Vertex v = graph.vertex(datatype);
		
		DatatypeRestriction r = new DatatypeRestriction();

		r.setOnDatatype(asURI(v.getValue(OwlVocab.onDatatype)));
		
		Vertex withRestrictions = v.vertexValue(OwlVocab.withRestrictions);
		if (withRestrictions != null) {
			List list = withRestrictions.asList();
			
			for (Value value : list) {
				if (value instanceof Resource) {
					Vertex w = graph.vertex((Resource)value);

					Double maxExclusive = w.doubleValue(XSD.maxExclusive);
					Double maxInclusive = w.doubleValue(XSD.maxInclusive);
					Integer maxLength = w.integerValue(XSD.maxLength);
					Double minExclusive = w.doubleValue(XSD.minExclusive);
					Double minInclusive = w.doubleValue(XSD.minInclusive);
					String pattern = w.stringValue(XSD.pattern);
					if (maxExclusive != null) {
						r.setMaxExclusive(maxExclusive);
					}
					if (maxInclusive != null) {
						r.setMaxInclusive(maxInclusive);
					}
					if (maxLength != null) {
						r.setMaxLength(maxLength);
					}
					if (minExclusive != null) {
						r.setMinExclusive(minExclusive);
					}
					if (minInclusive != null) {
						r.setMinInclusive(minInclusive);
					}
					if (pattern != null) {
						r.setPattern(pattern);
					}
				}
			}
		}
		
		
		return r;
	}

	

	private URI asURI(Value value) {
		return value instanceof URI ? (URI)value : null;
	}

	private Map getDatatypeMap() {
		if (datatypeMap == null) {
			datatypeMap = new HashMap<>();
		}
		return datatypeMap;
	}

	public Set superClasses(URI targetClass) {
		Vertex v = graph.getVertex(targetClass);
		if (v == null) {
			return Collections.emptySet();
		}
		return v.asTraversal().out(RDFS.SUBCLASSOF).toUriSet();
	}
	
	public Set disjointTypes(Collection types) {
		Set result = new HashSet<>();
		
		outerLoop :
		for (URI a : types) {
			Iterator sequence = result.iterator();
			
			while (sequence.hasNext()) {
				URI b = sequence.next();
				
				
				if (isSubClassOf(a, b)) {
					sequence.remove();
					break;
				}
				if (isSubClassOf(b, a)) {
					continue outerLoop;
				}
			}
			
			result.add(a);
			
		}
		
		return result;
	}
	
	/**
	 * Compute the specific types of a given individual.
	 * The returned set does not include any class that is a superclass of some other member of the set.
	 */
	public Set specificTypes(Resource individual) {
		Set result = null;
		Vertex v = graph.getVertex(individual);
		if (v != null) {
			Set edges = v.outProperty(RDF.TYPE);
			Set typeSet = new HashSet<>();
			for (Edge e : edges) {
				Value value = e.getObject();
				if (value instanceof URI) {
					typeSet.add((URI)value);
				}
			}
			result = disjointTypes(typeSet);
		} else {
			result = new HashSet<>();
		}
		
		return result;
	}

	public boolean isEnumerationMember(Resource id) {
		return isTypeOf(id, Schema.Enumeration);
	}
	
	public boolean isNamedIndividual(Resource subject) {
		return isTypeOf(subject, Schema.Enumeration) || isTypeOf(subject, OwlVocab.NamedIndividual);
	}

	public boolean isProperty(URI target) {
		return 
			isTypeOf(target, RDF.PROPERTY) ||
			isTypeOf(target, OWL.FUNCTIONALPROPERTY) ||
			isTypeOf(target, OWL.DATATYPEPROPERTY) ||
			isTypeOf(target, OWL.OBJECTPROPERTY) || 
			isTypeOf(target, OWL.ANNOTATIONPROPERTY) ||
			isTypeOf(target, OWL.DEPRECATEDPROPERTY) ||
			isTypeOf(target, OWL.EQUIVALENTPROPERTY) ||
			isTypeOf(target, OWL.INVERSEFUNCTIONALPROPERTY) ||
			isTypeOf(target, OWL.ONTOLOGYPROPERTY) ||
			isTypeOf(target, OWL.SYMMETRICPROPERTY) || 
			isTypeOf(target, OWL.TRANSITIVEPROPERTY);
	}

	public URI mostSpecificTypeOf(Vertex v) {
		Set typeSet = v.asTraversal().out(RDF.TYPE).toUriSet();
		return (URI) mostSpecificType(typeSet, null);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy