/*******************************************************************************
* Copyright 2012 University of Southern California
*
* 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.
*
* This code was developed by the Information Integration Group as part
* of the Karma project at the Information Sciences Institute of the
* University of Southern California. For more information, publications,
* and related projects, please see: http://www.isi.edu/integration
******************************************************************************/
package edu.isi.karma.er.helper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import edu.isi.karma.kr2rml.ObjectMap;
import edu.isi.karma.kr2rml.Predicate;
import edu.isi.karma.kr2rml.PredicateObjectMap;
import edu.isi.karma.kr2rml.R2RMLMapping;
import edu.isi.karma.kr2rml.RefObjectMap;
import edu.isi.karma.kr2rml.SubjectMap;
import edu.isi.karma.kr2rml.TriplesMap;
public class SPARQLGeneratorUtil {
private StringBuffer select_params;
private HashMap<String, String> prefix_list;
private int var_count;
private HashMap<String, ParentMapingInfo> ParentMapingInfoList;
private void SPARQLGeneratorUtil() {
this.var_count = 0;
}
// this
private class ParentMapingInfo {
public TriplesMap parent;
public Predicate predicate;
public ParentMapingInfo(TriplesMap triple, Predicate predicate) {
this.parent = triple;
this.predicate = predicate;
}
}
private String generate_sparql(TriplesMap node, String node_symbol, String graph) {
ArrayList<Object> queue = new ArrayList<Object>();
queue.add(node);
StringBuffer query = new StringBuffer();
this.var_count = 1;
this.prefix_list = new HashMap<String, String>();
this.select_params = new StringBuffer();
HashMap<TriplesMap, String> markedTriples = new HashMap<TriplesMap, String>();
this.ParentMapingInfoList = new HashMap<String, SPARQLGeneratorUtil.ParentMapingInfo>();
HashMap<Predicate, String> predicateList = new HashMap<Predicate, String>();
// using a BFS approach, we traverse the tree from the root node and add triples/predicates to the queue
while(queue.size() > 0) {
Object currentObj = queue.remove(0);
// if this is a tripleMap, then add all its RefObjects to the queue
// for the predicates, add only the ones that satisfy the criteria of being <...hasValue>
if (currentObj instanceof TriplesMap) {
String var = "x"+var_count;
TriplesMap triple = (TriplesMap)currentObj;
boolean foundHasValue = false;
List<PredicateObjectMap> predicates = triple.getPredicateObjectMaps();
for (PredicateObjectMap p_map : predicates) {
if(p_map.getObject().hasRefObjectMap()) {
RefObjectMap objMap = p_map.getObject().getRefObjectMap();
queue.add(objMap.getParentTriplesMap());
System.out.println(triple.getSubject().getId() + " ---> " + objMap.getParentTriplesMap().getSubject().getId());
// maintain a list of mapping properties between triples
ParentMapingInfoList.put(objMap.getParentTriplesMap().getSubject().getId(),
new ParentMapingInfo(triple, p_map.getPredicate()));
} else if(!foundHasValue) {
if(p_map.getPredicate().getTemplate().toString().equalsIgnoreCase("<http://www.opengis.net/gml/hasValue>")) {
queue.add(p_map.getPredicate());
predicateList.put(p_map.getPredicate(), var);
foundHasValue = true;
}
}
}
// if this triple is marked to be included in the query,
// we add it to the markedTriples list and add to the query string
// for its class type Eg.
// Prefix pref1: <.../.../Input>
// x2 a pref1:
if (foundHasValue) {
markedTriples.put(triple, var);
String rdfsTypes = triple.getSubject().getRdfsType().get(0).toString();
this.prefix_list.put(rdfsTypes, "pref"+var_count);
query.append(" ?"+var + " a pref"+var_count+": .");
// if the parent of this triple is also marked for the query
// then we add the relation to between triples to the query. Eg.
// TriplesMap parentTriple = parent.get(triple.getSubject().getId());
ParentMapingInfo parentTriple = ParentMapingInfoList.get(triple.getSubject().getId());
if( parentTriple != null && markedTriples.containsKey(parentTriple.parent)) {
String predicate = parentTriple.predicate.getTemplate().toString();
// PredicateObjectMap parentPredicate = getPredicateBetweenTriples(triple, parentTriple);
if(predicate != null) {
query.append(" ?" + markedTriples.get(parentTriple.parent) + " " +
predicate + " ?"+var + " . ");
} else {
System.out.println("predicate is null from parent : " + triple.getSubject().getRdfsType().toString());
}
}
}
var_count++;
}
// if it is a predicate Object, create a variable in in the query string
else if (currentObj instanceof Predicate) {
Predicate predicate = (Predicate)currentObj;
query.append(" ?" + predicateList.get(predicate)
+ " " + predicate.getTemplate() + " ?z"+ var_count + " . ");
select_params.append(" ?z" + var_count);
var_count++;
}
// if this is a RefObject add the Child Triple to the queue
else if (currentObj instanceof RefObjectMap) {
RefObjectMap refObj = (RefObjectMap)currentObj;
TriplesMap t = refObj.getParentTriplesMap();
queue.add(t);
}
}
// generate the query from the list of prefix and the param lists
Iterator<String> itr = this.prefix_list.keySet().iterator();
StringBuffer sQuery = new StringBuffer();
while(itr.hasNext()) {
String key = itr.next();
sQuery.append(" PREFIX ").append(this.prefix_list.get(key)).append(": ").append(key);
}
if(graph == null || graph.isEmpty()) {
sQuery.append(" select ").append(select_params).append(" where { ").append(query.toString()).append(" } ");
} else {
sQuery.append(" select ").append(select_params).append(" where { GRAPH <").append(graph)
.append("> { ").append(query.toString()).append(" } }");
}
System.out.println("Query : " + sQuery);
return sQuery.toString();
}
public String get_query(R2RMLMapping r2rmlMap, String graph) {
List<TriplesMap> triples = r2rmlMap.getTriplesMapList();
TriplesMap root_node = null;
// get the root node first
for (TriplesMap row : triples) {
if (row.getSubject().isSteinerTreeRootNode() ) {
root_node = row;
break;
}
}
return generate_sparql(root_node, "x"+var_count, graph);
}
}