package esl.cuenet.query; import com.hp.hpl.jena.datatypes.RDFDatatype; import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; import com.hp.hpl.jena.datatypes.xsd.impl.XSDDateTimeType; import com.hp.hpl.jena.graph.Node; import com.hp.hpl.jena.ontology.DatatypeProperty; import com.hp.hpl.jena.ontology.Individual; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.query.Query; import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.Statement; import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.sparql.core.TriplePath; import com.hp.hpl.jena.sparql.core.Var; import com.hp.hpl.jena.sparql.expr.Expr; import com.hp.hpl.jena.sparql.syntax.*; import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; import esl.cuenet.mapper.tree.SourceMapper; import esl.cuenet.model.Constants; import esl.cuenet.source.*; import esl.datastructures.graph.relationgraph.IRelationGraph; import esl.datastructures.graph.relationgraph.RelationGraphEdge; import esl.datastructures.graph.relationgraph.RelationGraphNode; import org.apache.log4j.Logger; import javax.xml.transform.Source; import java.util.ArrayList; import java.util.List; public class QueryEngine { Logger logger = Logger.getLogger(QueryEngine.class); private OntModel model = null; private QueryGraph queryGraph = new QueryGraph(); private SourceMapper sourceMapper = null; private List<String> projectTypeURIs = null; public QueryEngine(OntModel model, SourceMapper sourceMapper) { this.model = model; this.sourceMapper = sourceMapper; } public List<IResultSet> execute(String sparqlQuery) { String ns = "http://www.semanticweb.org/arjun/cuenet-main.owl"; Query query = QueryFactory.create(sparqlQuery); query.getQueryPattern().visit(new ElementVisitorImpl(queryGraph)); List<Var> projectVars = query.getProjectVars(); projectTypeURIs = new ArrayList<String>(); for (Var projectVar: projectVars) { RelationGraphNode node = queryGraph.getNodeByName(projectVar.toString()); for (RelationGraphEdge edge: queryGraph.getOutgoingEdges(node)) { if (edge.label().equalsIgnoreCase(RDF.type.getURI())) projectTypeURIs.add(queryGraph.getDestinationNode(edge).name()); } } logger.info("Finished parsing query"); // convert query triples to individuals and their attributes List<RelationGraphNode> allTypedNodes = queryGraph.getAllTypedNodes(); List<RelationGraphNode> attributeNodes = new ArrayList<RelationGraphNode>(); for (RelationGraphNode node : allTypedNodes) { boolean flag = true; for (Var projectVar : projectVars) if (node.name().equalsIgnoreCase(projectVar.toString())) flag = false; if (flag) attributeNodes.add(node); } List<Individual> individuals = new ArrayList<Individual>(); for (RelationGraphNode attrib : attributeNodes) { OntClass cl = model.getOntClass(ns + attrib.name()); Individual ind = model.createIndividual(cl); for (RelationGraphEdge edge : queryGraph.getOutgoingEdges(attrib)) { RelationGraphNode dest = queryGraph.getDestinationNode(edge); if (edge.label().equalsIgnoreCase(RDF.type.getURI())) ind.addProperty(RDF.type, model.getOntClass(dest.name())); else { Property property = model.getProperty(ns + edge.label()); ind.addLiteral(property, dest.name()); } } individuals.add(ind); } for (Var projectVar : projectVars) { RelationGraphNode node = queryGraph.getNodeByName(projectVar.toString()); OntClass cl = model.getOntClass(ns + node.name()); Individual individual = model.createIndividual(cl); boolean added = false; for (RelationGraphEdge edge: queryGraph.getOutgoingEdges(node)) { if(edge.label().compareTo(Constants.CuenetNamespace+ Constants.OccursDuring) == 0) { RelationGraphNode dest = queryGraph.getDestinationNode(edge); Literal l = model.createTypedLiteral(dest.name(), XSDDatatype.XSDdateTime); added = true; individual.addProperty(model.getProperty(Constants.CuenetNamespace+ Constants.OccursDuring), l); } if (edge.label().equalsIgnoreCase(RDF.type.getURI())) { RelationGraphNode dest = queryGraph.getDestinationNode(edge); individual.addProperty(RDF.type, model.getOntClass(dest.name())); } } if (added) individuals.add(individual); } List<IResultSet> results = eval(individuals); clear(); return results; } private void clear() { queryGraph = new QueryGraph(); } private List<IResultSet> eval(List<Individual> individuals) { if (sourceMapper == null) { logger.info("No sources added. Returning"); return null; } return sourceMapper.accept(new SourceVisitor(queryGraph, individuals)); } public class SourceVisitor implements SourceMapVisitor { private QueryGraph graph; private List<Individual> inputIndividuals; public SourceVisitor(QueryGraph graph, List<Individual> inputIndividuals) { this.graph = graph; this.inputIndividuals = inputIndividuals; } @Override public IResultSet visit(ISource source) { logger.info("Visiting " + source.getName()); //check if source describe with any project URI IRelationGraph relationGraph = source.getRelationGraph(); IMapper mapper = source.getMapper(); boolean flag = false; for (String uri: projectTypeURIs) { List<RelationGraphNode> nodes = relationGraph.getNodesOfType(removeNamespace(uri)); if (nodes != null && nodes.size() > 0) flag = true; // see if any subclasses can be found if (!flag) { List<OntClass> subclasses = getSubClasses(uri); for (OntClass ontClass: subclasses) { nodes = relationGraph.getNodesOfType(removeNamespace(ontClass.getURI())); if (nodes != null && nodes.size() > 0) flag = true; } } logger.info("Searching for: " + uri); } logger.info("Source *" + source.getName() + "* suitable for querying: " + flag); if (!flag) return null; List<String> pathExpressions = new ArrayList<String>(); List<Literal> literals = new ArrayList<Literal>(); for (Individual ind : inputIndividuals) { Statement s = ind.getProperty(RDF.type); String individualType = removeNamespace(s.getObject().toString()); List<RelationGraphNode> queryNodes = relationGraph.getNodesOfType(individualType); StmtIterator si; String pathExpr; for (RelationGraphNode queryNode : queryNodes) { si = ind.listProperties(); while (si.hasNext()) { Statement st = si.next(); if (!st.getPredicate().getURI().contains("cuenet")) continue; if (st.getObject().isLiteral()) { String p = removeNamespace(st.getPredicate().getURI()); pathExpr = queryNode.name() + "." + p; if (!mapper.containsPattern(pathExpr)) continue; Adornment a = mapper.getAdornment(pathExpr); if (a != null && a.type() == Adornment.AdornmentType.Unspecifiable) continue; logger.info("Query Params: " + pathExpr + ", " + st.getObject().asLiteral()); pathExpressions.add(pathExpr); literals.add(st.getObject().asLiteral()); } } } } if (pathExpressions.size() == 0 || literals.size() == 0 ) { logger.info("Zero input predicates for " + source.getName()); return null; } /* set the query attributes */ IResultSet resultsSet = null; try { resultsSet = source.query(pathExpressions, literals); } catch (SourceQueryException e) { e.printStackTrace(); } catch (AccesorInitializationException e) { e.printStackTrace(); } if (resultsSet != null) logger.info(resultsSet.printResults()); else logger.info("NULL Result Set"); return resultsSet; } private List<OntClass> getSubClasses(String uri) { List<OntClass> subClasses = new ArrayList<OntClass>(); // list all the sub classes. OntClass eventOntClass = model.getOntClass(uri); StmtIterator iterator = model.listStatements(null, RDFS.subClassOf, eventOntClass); while(iterator.hasNext()) { Statement stmt = iterator.nextStatement(); OntClass event = model.getOntClass(stmt.getSubject().getURI()); subClasses.add(event); } return subClasses; } private String removeNamespace(String uri) { int ix = uri.indexOf("#"); return uri.substring(ix+1); } } public class ElementVisitorImpl implements ElementVisitor { private QueryGraph graph = null; public ElementVisitorImpl(QueryGraph graph) { this.graph = graph; } @Override public void visit(ElementPathBlock el) { logger.info("Visit: Element Path Block"); for (TriplePath tp : el.getPattern().getList()) { Node sub = tp.getSubject(); Node pre = tp.getPredicate(); Node obj = tp.getObject(); RelationGraphNode subNode; if (graph.containsClass(sub.toString())) { subNode = graph.getNodeByName(sub.toString()); } else subNode = graph.createNode(sub.toString()); RelationGraphNode objNode; if (obj.isLiteral()) objNode = graph.createNode((String)obj.getLiteral().getValue()); else { if (graph.containsClass(obj.toString())) { objNode = graph.getNodeByName(obj.toString()); } else objNode = graph.createNode(obj.toString()); } graph.createEdge(pre.toString(), subNode, objNode); logger.info(sub.getName() + " <> " + pre.toString() + " <> " + obj.toString()); } } @Override public void visit(ElementFilter elementFilter) { Expr expr = elementFilter.getExpr(); logger.info("Visit: Element Filter " + expr.toString()); } @Override public void visit(ElementGroup el) { logger.info("Visit: Element Group"); for (Element m : el.getElements()) { m.visit(this); } } @Override public void visit(ElementTriplesBlock el) { } @Override public void visit(ElementAssign el) { } @Override public void visit(ElementBind elementBind) { } @Override public void visit(ElementUnion el) { } @Override public void visit(ElementOptional el) { } @Override public void visit(ElementDataset el) { } @Override public void visit(ElementNamedGraph el) { } @Override public void visit(ElementExists elementExists) { } @Override public void visit(ElementNotExists elementNotExists) { } @Override public void visit(ElementMinus elementMinus) { } @Override public void visit(ElementService el) { } @Override public void visit(ElementFetch el) { } @Override public void visit(ElementSubQuery el) { } } }