package eu.play_project.dcep.distributedetalis.join; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.hp.hpl.jena.graph.Node; import com.hp.hpl.jena.graph.Node_URI; import eu.play_project.dcep.distributedetalis.api.VariableBindings; /** * @author Ningyuan Pan */ public class HistoricalQueryContainer { final static String SELECT = "SELECT"; final static String WHERE = "WHERE"; final static String VALUES = "VALUES"; private final List<String> vvariables = new ArrayList<String>(); private final Map<String, List<Object>> map; private String query; private final Logger logger = LoggerFactory.getLogger(HistoricalQueryContainer.class); public HistoricalQueryContainer(String query, VariableBindings variableBindings){ if(query == null) throw new IllegalArgumentException("Original query should not be null"); map = new VariableBindings(); for (String varName : variableBindings.keySet()) { // Trasfer only variables with nonempty bindings: if (variableBindings.get(varName) != null && !variableBindings.get(varName).isEmpty()) { map.put(varName, variableBindings.get(varName)); } } if(map != null) this.query = addVALUES(query); else this.query = query; } public String getQuery(){ return query; } /** * Add VALUES block into queries */ private String addVALUES(String oquery){ int count = 0, index = 0; StringBuilder sparqlb = new StringBuilder(oquery); index = oquery.indexOf(VALUES); if(index != -1){ throw new IllegalArgumentException("Original query already has VALUES clause"); } else { index = oquery.indexOf(WHERE); logger.debug("where index: "+index); // add VALUES block in WHERE block if (index == -1){ throw new IllegalArgumentException("Original query has no WHERE clause"); } else{ while(index < oquery.length()){ if(oquery.charAt(index) == '{'){ count++; } else if(oquery.charAt(index) == '}'){ count--; if(count == 0){ break; } } index++; } String vb = makeVALUES(); sparqlb.insert(index, vb); } } return sparqlb.toString(); } /** * Make VALUES block using variables and its values */ private String makeVALUES(){ StringBuilder ret = new StringBuilder(); if(makeVariableList()){ ret.append("\n VALUES ( "); for(int i = 0; i < vvariables.size(); i++){ ret.append(vvariables.get(i)); ret.append(" "); } ret.append(") {"); ret = makeBody(ret, null, 0); ret.append("\n }\n"); } return ret.toString(); } private boolean makeVariableList(){ boolean ret = false; for(String variable : map.keySet()){ logger.debug("Add variable to list: " + variable); vvariables.add(variable); ret = true; } return ret; } /** * Make VALUES body of all combinations of values */ private StringBuilder makeBody(StringBuilder ret, StringBuilder p, int depth){ StringBuilder path = p; String pathMinusOne; if(depth == vvariables.size()){ path.append(")"); ret.append(path); } else if(depth == 0){ path = new StringBuilder(); List<Object> values = map.get(vvariables.get(depth)); if(values == null || values.isEmpty()){ path.append("\n ( UNDEF "); ret = makeBody(ret, path, depth+1); } else{ for(int i = 0; i < values.size(); i++){ path.delete(0, path.length()); path.append("\n ( "); path.append(makeVal(values.get(i))); path.append(" "); ret = makeBody(ret, path, depth+1); } } } else{ pathMinusOne = path.toString(); logger.debug(vvariables.get(depth)); logger.debug("{}", map.get(vvariables.get(depth))); List<Object> values = map.get(vvariables.get(depth)); if(values == null || values.isEmpty()){ path.append("UNDEF "); ret = makeBody(ret, path, depth+1); } else{ for(int i = 0; i < values.size(); i++){ path.delete(0, path.length()); path.append(pathMinusOne); path.append(makeVal(values.get(i)) + " "); ret = makeBody(ret, path, depth+1); } } } return ret; } /** * Covert a single value to String according to the value type. */ private String makeVal(Object value) { if (value instanceof String) { return "\"" + value + "\""; } else if (value instanceof Node_URI) { return "<" + value.toString() + ">"; } else if (value instanceof Node) { return ((Node)value).toString(true); } else { return value.toString(); } } }