/*
* Copyright (c) 2013, University of Toronto.
*
* 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.
*/
package edu.toronto.cs.xml2rdf.mapping;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import edu.toronto.cs.xml2rdf.jena.JenaUtils;
import edu.toronto.cs.xml2rdf.utils.LogUtils;
import edu.toronto.cs.xml2rdf.xml.XMLUtils;
public class Relation {
static boolean debug = true;
private String name;
private Entity entity;
private String targetEntity;
private ForeignLookupKey foreignLookupKey;
private String path;
private Element element;
public Relation(String name, Entity entity, String targetEntity,
ForeignLookupKey foreignLookupKey, String path,
Element element) {
this.name = name;
this.entity = entity;
this.targetEntity = targetEntity;
this.foreignLookupKey = foreignLookupKey;
this.path = path;
this.element = element;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Entity getEntity() {
return entity;
}
public void setEntity(Entity entity) {
this.entity = entity;
}
public String getTargetEntity() {
return targetEntity;
}
public void setTargetEntity(String targetEntity) {
this.targetEntity = targetEntity;
}
public ForeignLookupKey getForeignLookupKey() {
return foreignLookupKey;
}
public void setForeignLookupKey(ForeignLookupKey foreignLookupKey) {
this.foreignLookupKey = foreignLookupKey;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Element getElement() {
return element;
}
public void setElement(Element element) {
this.element = element;
}
public com.hp.hpl.jena.rdf.model.Property getJenaProperty(Model model) {
return model.createProperty(getName());
}
public void createRDFRelation(Model model, Resource instanceResource, Element item, Document dataDoc, String typePrefix)
throws XPathExpressionException {
NodeList relationNodeList = XMLUtils.getNodesByPath(path, item, dataDoc);
for (int i = 0; i < relationNodeList.getLength(); i++) {
Element relationElement = (Element) relationNodeList.item(i);
findAndAddLinkedResouces(model, relationElement, dataDoc, instanceResource, typePrefix);
}
}
private void findAndAddLinkedResouces(Model model,
Element item, Document dataDoc, Resource parentResouce, String typePrefix) throws XPathExpressionException {
//TODO: Fix it!
// createSPARQL();
// name="x.y.z.y"
// x
// ?x y ?y .
// ?y z ?z .
// ?z y ?y .
String whereClause = "WHERE {\n";
int j = 0;
whereClause += "?x0 rdf:type <" + getTargetEntity() + "> . \n";
for (Property lookupProperty : foreignLookupKey.getProperties()) {
String localValue = XMLUtils.getStringByPath(lookupProperty.getPath(), item, dataDoc).trim();
if (localValue.length() == 0) {
continue;
}
// localValue = localValue.replaceAll("\\s+", "\\\\\\\\s+");
localValue = JenaUtils.querify(localValue);
String[] splittedRelation = lookupProperty.getElement().getAttribute("name")
.replace(typePrefix, "")
.split("\\.");
int i;
for (i = 1; i < splittedRelation.length; i++) {
whereClause += "?x" + (i - 1) + "" + (i != 1 ? j : "") + " t:" + splittedRelation[i] + " ?x" + (i) + "" + j + ".\n";
}
whereClause += "FILTER (?x" + (i - 1) + (i != 1 ? j : "") + " = \"" + localValue + "\").\n";
j++;
}
whereClause += "} ";
String queryStr
= "PREFIX t: <" + typePrefix + ">\n"
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
+ "select ?x0 \n" + whereClause;
LogUtils.debug(this.getClass(), queryStr);
Query query = QueryFactory.create(queryStr);
QueryExecution qExec = null;
try {
qExec = QueryExecutionFactory.create(query, model);
ResultSet rs = qExec.execSelect();
while (rs.hasNext()) {
QuerySolution solution = rs.next();
RDFNode subject = solution.get("?x0");
parentResouce.addProperty(getJenaProperty(model), subject);
}
} catch (Exception e) {
if (debug) {
e.printStackTrace();
}
} finally {
if (qExec != null) {
qExec.close();
}
}
// for (Property lookupProperty: foreignLookupKey.getProperties()) {
// String localValue = XMLUtils.getStringByPath(lookupProperty.getPath(), item, dataDoc);
// Selector selector = new SimpleSelector(null, lookupProperty.getJenaProperty(model), localValue);
// StmtIterator iter = model.listStatements(selector);
//
// while (iter.hasNext()) {
// Statement stmt = iter.next();
// if (targetEntity.equals(stmt.getSubject().getProperty(RDF.type).getObject().toString())) {
// parentResouce.addProperty(getJenaProperty(model), stmt.getSubject());
// }
// }
// }
//
//
// for (Property lookupProperty: foreignLookupKey.getProperties()) {
// String localValue = XMLUtils.getStringByPath(lookupProperty.getPath(), item, dataDoc);
// Selector selector = new SimpleSelector(null, lookupProperty.getJenaProperty(model), localValue);
// StmtIterator iter = model.listStatements(selector);
//
// while (iter.hasNext()) {
// Statement stmt = iter.next();
// if (targetEntity.equals(stmt.getSubject().getProperty(RDF.type).getObject().toString())) {
// parentResouce.addProperty(getJenaProperty(model), stmt.getSubject());
// }
// }
// }
}
public String getSPARQLEqualPhrase(String parentVarName, String typePrefix, Model model, Element item, Document dataDoc) throws XPathExpressionException {
String clause = "";
NodeList relationNodeList = XMLUtils.getNodesByPath(path, item, dataDoc);
for (int i = 0; i < relationNodeList.getLength(); i++) {
Element relationElement = (Element) relationNodeList.item(i);
String relVarName = JenaUtils.getNextSparqlVarName();
clause += parentVarName + " <" + this.getName() + "> " + relVarName + " . \n";
for (Property lookupProperty : foreignLookupKey.getProperties()) {
String localValue = XMLUtils.getStringByPath(lookupProperty.getPath(), relationElement, dataDoc).trim();
if (localValue.length() == 0) {
continue;
}
// localValue = localValue.replaceAll("\\s+", "\\\\\\\\s+");
localValue = JenaUtils.querify(localValue);
String[] splittedRelation = lookupProperty.getElement().getAttribute("name")
.replace(typePrefix, "")
.split("\\.");
String currentVarName = relVarName;
String nextVarName = JenaUtils.getNextSparqlVarName();
int k;
for (k = 1; k < splittedRelation.length; k++) {
clause += currentVarName + " t:" + splittedRelation[k] + " " + nextVarName + ".\n";
currentVarName = nextVarName;
nextVarName = JenaUtils.getNextSparqlVarName();
}
clause += "FILTER (" + currentVarName + " = \"" + localValue + "\") . \n";
}
}
return clause;
}
}