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

io.konig.core.showl.ShowlServiceImpl Maven / Gradle / Ivy

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

/*
 * #%L
 * Konig Core
 * %%
 * Copyright (C) 2015 - 2019 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.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.openrdf.model.Namespace;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.model.vocabulary.RDF;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.konig.core.Edge;
import io.konig.core.Graph;
import io.konig.core.NamespaceManager;
import io.konig.core.OwlReasoner;
import io.konig.core.Vertex;
import io.konig.core.impl.RdfUtil;
import io.konig.core.vocab.Konig;
import io.konig.datasource.DataSource;
import io.konig.shacl.NodeKind;
import io.konig.shacl.PropertyConstraint;
import io.konig.shacl.Shape;
import io.konig.shacl.ShapeManager;

public class ShowlServiceImpl implements ShowlService {
	private static Logger logger = LoggerFactory.getLogger(ShowlServiceImpl.class);
	
	private Map classMap = new HashMap<>();
	private Map propertyMap = new HashMap<>();
	private Map enumNodeShapes = new HashMap<>();
	
	private OwlReasoner reasoner;
	private ShowlNodeShapeBuilder nodeBuilder;

	public ShowlServiceImpl(OwlReasoner reasoner) {
		this.reasoner = reasoner;
		nodeBuilder = new ShowlNodeShapeBuilder(this, this);
	}

	@Override
	public ShowlClass produceShowlClass(URI id) {
		ShowlClass owlClass = classMap.get(id);
		if (owlClass == null) {
			owlClass = new ShowlClass(reasoner, id);
			classMap.put(id,  owlClass);
		}
		return owlClass;
	}

	@Override
	public ShowlProperty produceProperty(URI predicate) {
		ShowlProperty property = propertyMap.get(predicate);
		if (property == null) {
			property = new ShowlProperty(predicate);
			propertyMap.put(predicate, property);

			URI domain = RdfUtil.uri(reasoner.getDomain(predicate));
			URI range = RdfUtil.uri(reasoner.getRange(predicate));
			
			if (domain != null) {
				property.setDomain(produceShowlClass(domain));
			}
			if (range != null) {
				property.setRange(produceShowlClass(range));
			}
		}
		return property;
	}

	@Override
	public ShowlNodeShape logicalNodeShape(URI owlClass) throws ShowlProcessingException {
		throw new ShowlProcessingException("not implemented yet");
	}

	@Override
	public ShowlNodeShape createNodeShape(Shape shape) throws ShowlProcessingException {
		return createShowlNodeShape(null, shape, produceShowlClass(shape.getTargetClass()));
	}

	@Override
	public ShowlNodeShape createNodeShape(Shape shape, DataSource ds) throws ShowlProcessingException {

		ShowlNodeShape node = createNodeShape(shape);
		ShowlDataSource dataSource = new ShowlDataSource(node, ds);
		node.setShapeDataSource(dataSource);
		return node;
	}

	@Override
	public ShowlClass inferDomain(ShowlProperty p) {
		return p.inferDomain(this);
	}

	@Override
	public ShowlClass inferRange(ShowlProperty p) {
		return p.inferRange(this);
	}

	@Override
	public ShowlClass mostSpecificClass(ShowlClass a, ShowlClass b) {

		ShowlClass result = 
			a==null ? b :
			b==null ? a :
			reasoner.isSubClassOf(a.getId(), b.getId()) ? a :
			b;
		
		return result==null ? produceShowlClass(Konig.Undefined) : result;
	}

	@Override
	public ShowlNodeShape createShowlNodeShape(ShowlPropertyShape accessor, Shape shape, ShowlClass owlClass) {
		
		return nodeBuilder.buildNodeShape(accessor, shape);
	}

	@Override
	public Set selectCandidateSources(ShowlNodeShape targetShape) {
		throw new ShowlProcessingException("not implemented yet");
	}

	@Override
	public ShapeManager getShapeManager() {

		throw new ShowlProcessingException("not implemented yet");
	}

	@Override
	public Graph getGraph() {
		return reasoner.getGraph();
	}

	@Override
	public OwlReasoner getOwlReasoner() {
		return reasoner;
	}

	@Override
	public Shape enumNodeShape(ShowlClass enumClass) throws ShowlProcessingException {
		
		Shape result = enumNodeShapes.get(enumClass.getId());
		if (result == null) {
			result = enumShape(enumClass.getId());
			enumNodeShapes.put(enumClass.getId(), result);
		}
		
		return result;
	}

	private Shape enumShape(URI classId) throws ShowlProcessingException {

		Graph graph = reasoner.getGraph();
		NamespaceManager nsManager = graph.getNamespaceManager();
		Namespace ns = nsManager.findByName(classId.getNamespace());
		if (ns == null) {
			throw new ShowlProcessingException("Prefix not found for namespace <" + classId.getNamespace() + ">");
		}
		StringBuilder builder = new StringBuilder();
		builder.append(ShowlUtil.ENUM_SHAPE_BASE_IRI);
		builder.append(ns.getPrefix());
		builder.append('/');
		builder.append(classId.getLocalName());
		
		URI shapeId = new URIImpl(builder.toString());
		
		Shape shape = new Shape(shapeId);
		shape.setNodeKind(NodeKind.IRI);
		shape.setTargetClass(classId);
		
		
		ShowlClass owlClass = classMap.get(classId);
		if (owlClass == null) {
			throw new ShowlProcessingException("ShowlClass not defined: " + classId);
		}
		
		addProperties(shape, owlClass);
		
		return shape;
	}

	private void addProperties(Shape shape, ShowlClass owlClass) throws  ShowlProcessingException {
		
		URI classId = owlClass.getId();
		
		List individualList = reasoner.getGraph().v(classId).in(RDF.TYPE).toVertexList();
		
		if (individualList.isEmpty()) {
			throw new ShowlProcessingException("No members found in enumeration " + classId.getLocalName());
		}
		
		for (Vertex member : individualList) {
		
			
			for (Entry> entry : member.outEdges()) {
				Set edgeSet  = entry.getValue();
				URI predicate = entry.getKey();
				if (predicate.equals(RDF.TYPE)) {
					continue;
				}
				if (edgeSet.size()>1) {
					logger.warn("Ignoring property {}.{} because multi-valued properties are not supported yet.", 
							classId.getLocalName(), predicate.getLocalName());
					continue;
				}

				ShowlProperty property = propertyMap.get(predicate);
				
				URI range = (property==null) ? 
						RdfUtil.uri(reasoner.getRange(predicate)) :  
						property.inferRange(reasoner);
				
				if (range == null) {
					logger.warn("Ignoring property {}.{} because the range is not known.",
							classId.getLocalName(), predicate.getLocalName());
					continue;
				}

				PropertyConstraint constraint = shape.getPropertyConstraint(predicate);
				if (constraint==null) {
					constraint = new PropertyConstraint(predicate);
					shape.add(constraint);
				
					if (reasoner.isDatatype(range)) {
						constraint.setDatatype(range);
					} else {
						constraint.setValueClass(range);
						
						// For now, we don't support nested shapes on enumeration classes.
						constraint.setNodeKind(NodeKind.IRI);
						
					}
					// For now we require that every property be optional and single-valued
					constraint.setMinCount(0);
					constraint.setMaxCount(1);
			
				}
			}
		}
		if (shape.getProperty().isEmpty()) {
			throw new ShowlProcessingException("No properties found in enumeration class " + classId.getLocalName());
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy