/// <summary> /// Get the result table of the given pattern group /// </summary> internal static void CombinePatterns(RDFConstructQuery query, RDFPatternGroup patternGroup) { if (patternGroup.Patterns.Any()) { //Populate pattern group result table DataTable patternGroupResultTable = RDFQueryEngine.CombineTables(query.PatternResultTables[patternGroup], false); //Add it to the list of pattern group result tables query.PatternGroupResultTables.Add(patternGroup, patternGroupResultTable); //Populate its metadata query.PatternGroupResultTables[patternGroup].TableName = patternGroup.ToString(); if (!query.PatternGroupResultTables[patternGroup].ExtendedProperties.ContainsKey("IsOptional")) { query.PatternGroupResultTables[patternGroup].ExtendedProperties.Add("IsOptional", patternGroup.IsOptional); } else { query.PatternGroupResultTables[patternGroup].ExtendedProperties["IsOptional"] = patternGroup.IsOptional; } if (!query.PatternGroupResultTables[patternGroup].ExtendedProperties.ContainsKey("JoinAsUnion")) { query.PatternGroupResultTables[patternGroup].ExtendedProperties.Add("JoinAsUnion", patternGroup.JoinAsUnion); } else { query.PatternGroupResultTables[patternGroup].ExtendedProperties["JoinAsUnion"] = patternGroup.JoinAsUnion; } } }
/// <summary> /// Apply the filters of the given pattern group to its result table /// </summary> internal static void ApplyFilters(RDFConstructQuery query, RDFPatternGroup patternGroup) { if (patternGroup.Patterns.Any() && patternGroup.Filters.Any()) { DataTable filteredTable = query.PatternGroupResultTables[patternGroup].Clone(); IEnumerator rowsEnum = query.PatternGroupResultTables[patternGroup].Rows.GetEnumerator(); //Iterate the rows of the pattern group's result table Boolean keepRow = false; while (rowsEnum.MoveNext()) { //Apply the pattern group's filters on the row keepRow = true; IEnumerator <RDFFilter> filtersEnum = patternGroup.Filters.GetEnumerator(); while (keepRow && filtersEnum.MoveNext()) { keepRow = filtersEnum.Current.ApplyFilter((DataRow)rowsEnum.Current, false); } //If the row has passed all the filters, keep it in the filtered result table if (keepRow) { DataRow newRow = filteredTable.NewRow(); newRow.ItemArray = ((DataRow)rowsEnum.Current).ItemArray; filteredTable.Rows.Add(newRow); } } //Save the result datatable query.PatternGroupResultTables[patternGroup] = filteredTable; } }
/// <summary> /// Apply the filters of the given pattern group to its result table /// </summary> internal static void ApplyFilters(RDFConstructQuery query, RDFPatternGroup patternGroup) { if (patternGroup.Patterns.Any() && patternGroup.Filters.Any()) { DataTable filteredTable = query.PatternGroupResultTables[patternGroup].Clone(); IEnumerator rowsEnum = query.PatternGroupResultTables[patternGroup].Rows.GetEnumerator(); //Iterate the rows of the pattern group's result table Boolean keepRow = false; while (rowsEnum.MoveNext()) { //Apply the pattern group's filters on the row keepRow = true; IEnumerator<RDFFilter> filtersEnum = patternGroup.Filters.GetEnumerator(); while (keepRow && filtersEnum.MoveNext()) { keepRow = filtersEnum.Current.ApplyFilter((DataRow)rowsEnum.Current, false); } //If the row has passed all the filters, keep it in the filtered result table if (keepRow) { DataRow newRow = filteredTable.NewRow(); newRow.ItemArray = ((DataRow)rowsEnum.Current).ItemArray; filteredTable.Rows.Add(newRow); } } //Save the result datatable query.PatternGroupResultTables[patternGroup] = filteredTable; } }
/// <summary> /// Apply the query modifiers to the query result table /// </summary> internal static DataTable ApplyModifiers(RDFConstructQuery query, DataTable table) { String tablenameBak = table.TableName; //Apply the DISTINCT modifier table = new RDFDistinctModifier().ApplyModifier(table); //Apply the OFFSET modifier table = query.Modifiers.Where(m => m is RDFOffsetModifier) .Aggregate(table, (current, modifier) => modifier.ApplyModifier(current)); //Apply the LIMIT modifier table = query.Modifiers.Where(m => m is RDFLimitModifier) .Aggregate(table, (current, modifier) => modifier.ApplyModifier(current)); table.TableName = tablenameBak; return(table); }
/// <summary> /// Get the intermediate result tables of the given pattern group /// </summary> internal static void EvaluatePatterns(RDFConstructQuery query, RDFPatternGroup patternGroup, Object graphOrStore) { query.PatternResultTables[patternGroup] = new List <DataTable>(); //Iterate over the patterns of the pattern group foreach (RDFPattern pattern in patternGroup.Patterns) { //Apply the pattern to the graph/store DataTable patternResultsTable = graphOrStore is RDFGraph?RDFQueryEngine.ApplyPattern(pattern, (RDFGraph)graphOrStore) : RDFQueryEngine.ApplyPattern(pattern, (RDFStore)graphOrStore); //Set the name and the optionality metadata of the result datatable patternResultsTable.TableName = pattern.ToString(); patternResultsTable.ExtendedProperties.Add("IsOptional", pattern.IsOptional); patternResultsTable.ExtendedProperties.Add("JoinAsUnion", pattern.JoinAsUnion); //Save the result datatable query.PatternResultTables[patternGroup].Add(patternResultsTable); } }
/// <summary> /// Get the intermediate result tables of the given pattern group /// </summary> internal static void EvaluatePatterns(RDFConstructQuery query, RDFPatternGroup patternGroup, Object graphOrStore) { query.PatternResultTables[patternGroup] = new List<DataTable>(); //Iterate over the patterns of the pattern group foreach (RDFPattern pattern in patternGroup.Patterns) { //Apply the pattern to the graph/store DataTable patternResultsTable = graphOrStore is RDFGraph ? RDFQueryEngine.ApplyPattern(pattern, (RDFGraph)graphOrStore) : RDFQueryEngine.ApplyPattern(pattern, (RDFStore)graphOrStore); //Set the name and the optionality metadata of the result datatable patternResultsTable.TableName = pattern.ToString(); patternResultsTable.ExtendedProperties.Add("IsOptional", pattern.IsOptional); patternResultsTable.ExtendedProperties.Add("JoinAsUnion", pattern.JoinAsUnion); //Save the result datatable query.PatternResultTables[patternGroup].Add(patternResultsTable); } }
/// <summary> /// Prints the string representation of a SPARQL CONSTRUCT query /// </summary> internal static String PrintConstructQuery(RDFConstructQuery constructQuery) { StringBuilder sb = new StringBuilder(); if (constructQuery != null) { #region PREFIXES if (constructQuery.Prefixes.Any()) { constructQuery.Prefixes.ForEach(pf => { sb.Append("PREFIX " + pf.NamespacePrefix + ": <" + pf.NamespaceUri + ">\n"); }); sb.Append("\n"); } #endregion #region HEADER #region BEGINCONSTRUCT sb.Append("CONSTRUCT"); #endregion #region TEMPLATES sb.Append("\n{\n"); constructQuery.Templates.ForEach(tp => { String tpString = PrintPattern(tp, constructQuery.Prefixes); //Remove the Context from the template print (since it is not supported by CONSTRUCT query) if (tp.Context != null) { tpString = tpString.Replace("GRAPH " + tp.Context + " { ", String.Empty).TrimEnd(new Char[] { ' ', '}' }); } //Remove the Optional indicator from the template print (since it is not supported by CONSTRUCT query) if (tp.IsOptional) { tpString = tpString.Replace("OPTIONAL { ", String.Empty).TrimEnd(new Char[] { ' ', '}' }); } sb.Append(" " + tpString + " .\n"); }); sb.Append("}\n"); #endregion #endregion #region BODY sb.Append("WHERE {\n"); #region MEMBERS Boolean printingUnion = false; List <RDFQueryMember> evaluableQueryMembers = constructQuery.GetEvaluableQueryMembers().ToList(); RDFQueryMember lastQueryMbr = evaluableQueryMembers.LastOrDefault(); foreach (var queryMember in evaluableQueryMembers) { #region PATTERNGROUPS if (queryMember is RDFPatternGroup) { //Current pattern group is set as UNION with the next one if (((RDFPatternGroup)queryMember).JoinAsUnion) { //Current pattern group IS NOT the last of the query //(so UNION keyword must be appended at last) if (!queryMember.Equals(lastQueryMbr)) { //Begin a new Union block if (!printingUnion) { printingUnion = true; sb.Append(" {\n"); } sb.Append(PrintPatternGroup((RDFPatternGroup)queryMember, 2, true, constructQuery.Prefixes)); sb.Append(" UNION\n"); } //Current pattern group IS the last of the query //(so UNION keyword must not be appended at last) else { //End the Union block if (printingUnion) { printingUnion = false; sb.Append(PrintPatternGroup((RDFPatternGroup)queryMember, 2, true, constructQuery.Prefixes)); sb.Append(" }\n"); } else { sb.Append(PrintPatternGroup((RDFPatternGroup)queryMember, 0, false, constructQuery.Prefixes)); } } } //Current pattern group is set as INTERSECT with the next one else { //End the Union block if (printingUnion) { printingUnion = false; sb.Append(PrintPatternGroup((RDFPatternGroup)queryMember, 2, true, constructQuery.Prefixes)); sb.Append(" }\n"); } else { sb.Append(PrintPatternGroup((RDFPatternGroup)queryMember, 0, false, constructQuery.Prefixes)); } } } #endregion #region SUBQUERY else if (queryMember is RDFQuery) { //Merge main query prefixes constructQuery.Prefixes.ForEach(pf1 => { if (!((RDFSelectQuery)queryMember).Prefixes.Any(pf2 => pf2.Equals(pf1))) { ((RDFSelectQuery)queryMember).AddPrefix(pf1); } }); //Current subquery is set as UNION with the next one if (((RDFSelectQuery)queryMember).JoinAsUnion) { //Current subquery IS NOT the last of the query //(so UNION keyword must be appended at last) if (!queryMember.Equals(lastQueryMbr)) { //Begin a new Union block if (!printingUnion) { printingUnion = true; sb.Append(" {\n"); } sb.Append(PrintSelectQuery((RDFSelectQuery)queryMember, 1, true)); sb.Append(" UNION\n"); } //Current query IS the last of the query //(so UNION keyword must not be appended at last) else { //End the Union block if (printingUnion) { printingUnion = false; sb.Append(PrintSelectQuery((RDFSelectQuery)queryMember, 1, true)); sb.Append(" }\n"); } else { sb.Append(PrintSelectQuery((RDFSelectQuery)queryMember, 1, false)); } } } //Current query is set as INTERSECT with the next one else { //End the Union block if (printingUnion) { printingUnion = false; sb.Append(PrintSelectQuery((RDFSelectQuery)queryMember, 1, true)); sb.Append(" }\n"); } else { sb.Append(PrintSelectQuery((RDFSelectQuery)queryMember, 1, false)); } } } #endregion } #endregion sb.Append("}"); #endregion #region FOOTER #region MODIFIERS List <RDFModifier> modifiers = constructQuery.GetModifiers().ToList(); // LIMIT/OFFSET if (modifiers.Any(mod => mod is RDFLimitModifier || mod is RDFOffsetModifier)) { modifiers.Where(mod => mod is RDFLimitModifier) .ToList() .ForEach(lim => { sb.Append("\n"); sb.Append(lim); }); modifiers.Where(mod => mod is RDFOffsetModifier) .ToList() .ForEach(off => { sb.Append("\n"); sb.Append(off); }); } #endregion #endregion } return(sb.ToString()); }
/// <summary> /// Fills the templates of the given query with data from the given result table /// </summary> internal static DataTable FillTemplates(RDFConstructQuery constructQuery, DataTable resultTable) { //Create the structure of the result datatable DataTable result = new DataTable("CONSTRUCT_RESULTS"); result.Columns.Add("SUBJECT", Type.GetType("System.String")); result.Columns.Add("PREDICATE", Type.GetType("System.String")); result.Columns.Add("OBJECT", Type.GetType("System.String")); result.AcceptChanges(); //Initialize working variables Dictionary <String, String> constructRow = new Dictionary <String, String>(); constructRow.Add("SUBJECT", null); constructRow.Add("PREDICATE", null); constructRow.Add("OBJECT", null); //Iterate on the templates foreach (RDFPattern tp in constructQuery.Templates.Where(tp => tp.Variables.Count == 0 || tp.Variables.TrueForAll(v => resultTable.Columns.Contains(v.ToString())))) { #region GROUND TEMPLATE //Check if the template is ground, so represents an explicit triple to be added as-is if (tp.Variables.Count == 0) { constructRow["SUBJECT"] = tp.Subject.ToString(); constructRow["PREDICATE"] = tp.Predicate.ToString(); constructRow["OBJECT"] = tp.Object.ToString(); RDFQueryUtilities.AddRow(result, constructRow); continue; } #endregion #region NON-GROUND TEMPLATE //Iterate the result datatable's rows to construct the triples of the current template IEnumerator rowsEnum = resultTable.Rows.GetEnumerator(); while (rowsEnum.MoveNext()) { #region SUBJECT //Subject of the template is a variable if (tp.Subject is RDFVariable) { //Check if the template must be skipped, in order to not produce illegal triples //Row contains an unbound value in position of the variable corresponding to the template subject if (((DataRow)rowsEnum.Current).IsNull(tp.Subject.ToString())) { continue; } RDFPatternMember subj = RDFQueryUtilities.ParseRDFPatternMember(((DataRow)rowsEnum.Current)[tp.Subject.ToString()].ToString()); //Row contains a literal in position of the variable corresponding to the template subject if (subj is RDFLiteral) { continue; } //Row contains a resource in position of the variable corresponding to the template subject constructRow["SUBJECT"] = subj.ToString(); } //Subject of the template is a resource else { constructRow["SUBJECT"] = tp.Subject.ToString(); } #endregion #region PREDICATE //Predicate of the template is a variable if (tp.Predicate is RDFVariable) { //Check if the template must be skipped, in order to not produce illegal triples //Row contains an unbound value in position of the variable corresponding to the template predicate if (((DataRow)rowsEnum.Current).IsNull(tp.Predicate.ToString())) { continue; } RDFPatternMember pred = RDFQueryUtilities.ParseRDFPatternMember(((DataRow)rowsEnum.Current)[tp.Predicate.ToString()].ToString()); //Row contains a blank resource or a literal in position of the variable corresponding to the template predicate if ((pred is RDFResource && ((RDFResource)pred).IsBlank) || pred is RDFLiteral) { continue; } //Row contains a non-blank resource in position of the variable corresponding to the template predicate constructRow["PREDICATE"] = pred.ToString(); } //Predicate of the template is a resource else { constructRow["PREDICATE"] = tp.Predicate.ToString(); } #endregion #region OBJECT //Object of the template is a variable if (tp.Object is RDFVariable) { //Check if the template must be skipped, in order to not produce illegal triples //Row contains an unbound value in position of the variable corresponding to the template object if (((DataRow)rowsEnum.Current).IsNull(tp.Object.ToString())) { continue; } RDFPatternMember obj = RDFQueryUtilities.ParseRDFPatternMember(((DataRow)rowsEnum.Current)[tp.Object.ToString()].ToString()); //Row contains a resource or a literal in position of the variable corresponding to the template object constructRow["OBJECT"] = obj.ToString(); } //Object of the template is a resource or a literal else { constructRow["OBJECT"] = tp.Object.ToString(); } #endregion //Insert the triple into the final table RDFQueryUtilities.AddRow(result, constructRow); } #endregion } return(result); }
/// <summary> /// Apply the query modifiers to the query result table /// </summary> internal static DataTable ApplyModifiers(RDFConstructQuery query, DataTable table) { String tablenameBak = table.TableName; //Apply the DISTINCT modifier table = new RDFDistinctModifier().ApplyModifier(table); //Apply the OFFSET modifier table = query.Modifiers.Where(m => m is RDFOffsetModifier) .Aggregate(table, (current, modifier) => modifier.ApplyModifier(current)); //Apply the LIMIT modifier table = query.Modifiers.Where(m => m is RDFLimitModifier) .Aggregate(table, (current, modifier) => modifier.ApplyModifier(current)); table.TableName = tablenameBak; return table; }
/// <summary> /// Fills the templates of the given query with data from the given result table /// </summary> internal static DataTable FillTemplates(RDFConstructQuery constructQuery, DataTable resultTable) { //Create the structure of the result datatable DataTable result = new DataTable("CONSTRUCT_RESULTS"); result.Columns.Add("SUBJECT", Type.GetType("System.String")); result.Columns.Add("PREDICATE", Type.GetType("System.String")); result.Columns.Add("OBJECT", Type.GetType("System.String")); result.AcceptChanges(); //Initialize working variables Dictionary<String, String> constructRow = new Dictionary<String, String>(); constructRow.Add("SUBJECT", null); constructRow.Add("PREDICATE", null); constructRow.Add("OBJECT", null); //Iterate on the templates foreach (RDFPattern tp in constructQuery.Templates.Where(tp => tp.Variables.Count == 0 || tp.Variables.TrueForAll(v => resultTable.Columns.Contains(v.ToString())))) { #region GROUND TEMPLATE //Check if the template is ground, so represents an explicit triple to be added as-is if (tp.Variables.Count == 0) { constructRow["SUBJECT"] = tp.Subject.ToString(); constructRow["PREDICATE"] = tp.Predicate.ToString(); constructRow["OBJECT"] = tp.Object.ToString(); RDFQueryUtilities.AddRow(result, constructRow); continue; } #endregion #region NON-GROUND TEMPLATE //Iterate the result datatable's rows to construct the triples of the current template IEnumerator rowsEnum = resultTable.Rows.GetEnumerator(); while (rowsEnum.MoveNext()) { #region SUBJECT //Subject of the template is a variable if (tp.Subject is RDFVariable) { //Check if the template must be skipped, in order to not produce illegal triples //Row contains an unbound value in position of the variable corresponding to the template subject if (((DataRow)rowsEnum.Current).IsNull(tp.Subject.ToString())) { continue; } RDFPatternMember subj = RDFQueryUtilities.ParseRDFPatternMember(((DataRow)rowsEnum.Current)[tp.Subject.ToString()].ToString()); //Row contains a literal in position of the variable corresponding to the template subject if (subj is RDFLiteral) { continue; } //Row contains a resource in position of the variable corresponding to the template subject constructRow["SUBJECT"] = subj.ToString(); } //Subject of the template is a resource else { constructRow["SUBJECT"] = tp.Subject.ToString(); } #endregion #region PREDICATE //Predicate of the template is a variable if (tp.Predicate is RDFVariable) { //Check if the template must be skipped, in order to not produce illegal triples //Row contains an unbound value in position of the variable corresponding to the template predicate if (((DataRow)rowsEnum.Current).IsNull(tp.Predicate.ToString())) { continue; } RDFPatternMember pred = RDFQueryUtilities.ParseRDFPatternMember(((DataRow)rowsEnum.Current)[tp.Predicate.ToString()].ToString()); //Row contains a blank resource or a literal in position of the variable corresponding to the template predicate if ((pred is RDFResource && ((RDFResource)pred).IsBlank) || pred is RDFLiteral) { continue; } //Row contains a non-blank resource in position of the variable corresponding to the template predicate constructRow["PREDICATE"] = pred.ToString(); } //Predicate of the template is a resource else { constructRow["PREDICATE"] = tp.Predicate.ToString(); } #endregion #region OBJECT //Object of the template is a variable if (tp.Object is RDFVariable) { //Check if the template must be skipped, in order to not produce illegal triples //Row contains an unbound value in position of the variable corresponding to the template object if (((DataRow)rowsEnum.Current).IsNull(tp.Object.ToString())) { continue; } RDFPatternMember obj = RDFQueryUtilities.ParseRDFPatternMember(((DataRow)rowsEnum.Current)[tp.Object.ToString()].ToString()); //Row contains a resource or a literal in position of the variable corresponding to the template object constructRow["OBJECT"] = obj.ToString(); } //Object of the template is a resource or a literal else { constructRow["OBJECT"] = tp.Object.ToString(); } #endregion //Insert the triple into the final table RDFQueryUtilities.AddRow(result, constructRow); } #endregion } return result; }