edu.isi.karma.er.helper.SPARQLGeneratorUtil.java Source code

Java tutorial

Introduction

Here is the source code for edu.isi.karma.er.helper.SPARQLGeneratorUtil.java

Source

/*******************************************************************************
 * 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 java.util.Stack;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import edu.isi.karma.kr2rml.Predicate;
import edu.isi.karma.kr2rml.PredicateObjectMap;
import edu.isi.karma.kr2rml.RefObjectMap;
import edu.isi.karma.kr2rml.mapping.R2RMLMapping;
import edu.isi.karma.kr2rml.planning.TriplesMap;

/**
 * @author shri
 * */
public class SPARQLGeneratorUtil {

    private static Logger logger = LoggerFactory.getLogger(SPARQLGeneratorUtil.class);
    private StringBuffer select_params;
    private HashMap<String, String> prefix_list;
    private int var_count;
    private HashMap<String, ParentMapingInfo> ParentMapingInfoList;

    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<>();
        queue.add(node);
        StringBuffer query = new StringBuffer();
        this.var_count = 1;
        this.prefix_list = new HashMap<>();
        this.select_params = new StringBuffer();
        HashMap<TriplesMap, String> markedTriples = new HashMap<>();

        this.ParentMapingInfoList = new HashMap<>();

        HashMap<Predicate, String> predicateList = new HashMap<>();

        // using a BFS approach, we traverse the tree from the root node and add triples/predicates to the queue
        while (!queue.isEmpty()) {
            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 there are tripleMaps linked to the current tripleMap, then
                    // we need to save their relation/linkage between them
                    if (p_map.getObject().hasRefObjectMap()) {
                        RefObjectMap objMap = p_map.getObject().getRefObjectMap();
                        queue.add(objMap.getParentTriplesMap());

                        logger.info(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 {
                            logger.error("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(" } }");
        }
        logger.info("Genreated 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);
    }

    public String get_query(TriplesMap root, ArrayList<HashMap<String, String>> columns) {
        return get_query(root, columns, false);
    }

    /**
     * @author shri
     * This method will genereate a sparql query to select the list of columns (in the order they are provided)
     * 
     * @param root This object of TriplesMap is the root from which this method begins to fetch columns
     * @param columns This ArrayList<String> has the list of columns to be fetched. These columns are identifyed by their complete URL as defined in the ontology. <br /> 
     * For example: <http://isi.edu/integration/karma/ontologies/model/accelerometer#AccelerometerReading>. Now there may exists many instance of a class in within the same ontology. 
     * */
    public String get_query(TriplesMap root, ArrayList<HashMap<String, String>> columns, boolean distinct_query) {

        ArrayList<Object> queue = new ArrayList<>();
        queue.add(root);
        StringBuffer query = new StringBuffer();
        this.var_count = 1;
        this.prefix_list = new HashMap<>();
        this.select_params = new StringBuffer();
        //      ArrayList<String> select_param = new ArrayList<String>();
        HashMap<TriplesMap, String> markedTriples = new HashMap<>();

        ArrayList<String> visited_columns = new ArrayList<>();
        this.ParentMapingInfoList = new HashMap<>();

        // save the column predicate url and the column name to be dislayed
        HashMap<Predicate, String> predicateList = new HashMap<>();
        HashMap<String, String> columnList = new HashMap<>();
        if (columns != null && !columns.isEmpty()) {
            //         for (String k : columns) {
            //            int index = 0;
            //            if(k.indexOf("#") > 0) {
            //               index = k.lastIndexOf('#')+1;
            //            } else if(k.indexOf("/") > 0) {
            //               index = k.lastIndexOf('/')+1;
            //            }
            //            columnList.put(k, k.substring(index, k.length()));
            //         }
            for (HashMap<String, String> col : columns) {
                columnList.put(col.get("name"), col.get("url"));
            }
        }

        // using a BFS approach, we traverse the tree from the root node and add triples/predicates to the queue
        while (!queue.isEmpty()) {
            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());

                        logger.info(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 {
                        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("pref" + var_count, rdfsTypes);
                    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());

                    // from the current node, keep poping out till we reach the last node in the 
                    // parent map to see if any of the parents are connected
                    if (parentTriple != null) {
                        String sq = checkParentMarked(triple, markedTriples, var);
                        if (sq.length() > 1) {
                            query.append(sq);
                        }

                    }
                    //               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;
                String k = predicate.getTemplate().toString();
                k = k.replace('<', ' ').replace('>', ' ').trim();
                if (columns != null && !columns.isEmpty()) {
                    //               if(columnList.containsKey(k)) {
                    if (columnList.containsValue(k)) {
                        Iterator<String> itr = columnList.keySet().iterator();
                        while (itr.hasNext()) {
                            String cName = itr.next();
                            if (columnList.get(cName).equals(k) && !visited_columns.contains(cName)) {
                                // get the column name from the end of this url - either the last '/' or the '#'
                                query.append(" ?" + predicateList.get(predicate)).append(" ")
                                        .append(predicate.getTemplate()).append(" ?").append(cName + " . ");
                                //columnList.remove(cName);
                                visited_columns.add(cName);
                                var_count++;
                                break;
                            }
                        }
                        // get the column name from the end of this url - either the last '/' or the '#'
                        //                  query.append(" ?" + predicateList.get(predicate))
                        //                     .append(" ")
                        //                     .append(predicate.getTemplate())
                        //                     .append(" ?")
                        //                     .append(columnList.get(k) + " . ");
                        //                  var_count++;
                    } else {
                        logger.info("ColumnList does not contain : " + k + " " + currentObj);
                    }
                } else {
                    int index = 0;
                    if (k.indexOf("#") > 0) {
                        index = k.lastIndexOf('#') + 1;
                    } else if (k.indexOf("/") > 0) {
                        index = k.lastIndexOf('/') + 1;
                    }
                    query.append(" ?" + predicateList.get(predicate)).append(" ").append(predicate.getTemplate())
                            .append(" ?").append(k.substring(index, k.length())).append(" .");
                    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);

            }
        }

        // append the list of prefixes
        Iterator<String> itr = this.prefix_list.keySet().iterator();
        StringBuffer sQuery = new StringBuffer();
        while (itr.hasNext()) {
            String key = itr.next();
            sQuery.append(" PREFIX ").append(key).append(": ").append(this.prefix_list.get(key));
        }
        // append the columns to be selected in the order they are specified
        sQuery.append(" select ");
        if (distinct_query) {
            sQuery.append(" distinct ");
        }
        for (HashMap<String, String> s : columns) {
            sQuery.append(" ?" + s.get("name"));
        }
        sQuery.append(" where { ").append(query.toString()).append(" } ");
        logger.info("Generated Query : " + sQuery);
        return sQuery.toString();
    }

    private String checkParentMarked(TriplesMap triple, HashMap<TriplesMap, String> markedTriples, String var1) {
        Stack<String> stk = new Stack<>();
        ParentMapingInfo parentTriple = this.ParentMapingInfoList.get(triple.getSubject().getId());
        boolean markedParent = false;
        int count = 1;
        String previous = var1;
        while (parentTriple != null) {
            String predicate = parentTriple.predicate.getTemplate().toString();

            if (markedTriples.get(parentTriple.parent) == null) {

                markedTriples.put(parentTriple.parent, "Z" + count);
                String rdfsTypes = parentTriple.parent.getSubject().getRdfsType().get(0).toString();
                this.prefix_list.put("pref" + "Z" + count, rdfsTypes);
                stk.push(" ?Z" + count + " a pref" + "Z" + count + ": .");
                stk.push(" ?" + markedTriples.get(parentTriple.parent) + " " + predicate + " ?" + previous + " . ");
            } else {
                stk.push(" ?" + markedTriples.get(parentTriple.parent) + " " + predicate + " ?" + previous + " . ");
                markedParent = true;
                break;
            }
            previous = markedTriples.get(parentTriple.parent);
            parentTriple = this.ParentMapingInfoList.get(parentTriple.parent.getSubject().getId());
            if (parentTriple == null) {
                break;
            }
            var1 = markedTriples.get(parentTriple.parent);
            //         if(markedTriples.containsKey(parentTriple.parent)) {
            //            markedParent = true;
            //            stk.push(" ?" + markedTriples.get(parentTriple.parent) + " " + 
            //                  predicate + " ?"+var1 + " . ");
            //            break;
            //         }
        }

        if (markedParent) {
            return StringUtils.join(stk, " ");
        }
        return "";
    }

}