/// <summary> /// Creates the projection part of the SPARQL query - the part that specifies which data to return back. /// </summary> /// <param name="sb">A <see cref="StringBuilder"/> into which the projection is inserted.</param> private void CreateProjection(StringBuilder sb) { string distinct = Expressions.ContainsKey("Distinct") ? "DISTINCT " : String.Empty; //Can use REDUCED if Distinct not specified if (distinct.Equals(String.Empty)) { if (Expressions.ContainsKey("Reduced")) { distinct = "REDUCED "; } } if (Expressions.ContainsKey("Select")) { BuildProjection(Expressions["Select"]); } sb.Append("SELECT " + distinct); if (Expressions.ContainsKey("GroupBy")) { throw new NotSupportedException("Group By is not supported by VDS.RDF.Linq"); } // if it is of the form "from a in b select a" if (ProjectionParameters.Count == 0) { foreach (MemberInfo mi in OwlClassSupertype.GetAllPersistentProperties(typeof(T))) { sb.Append(" ?"); sb.Append(mi.Name); } } else // if it is of the form "from a in b select new {a.c, a.d, a.e}" then add c,d,e to the projection { foreach (MemberInfo mi in ProjectionParameters) { sb.Append(" ?"); sb.Append(mi.Name); } } // add a parameter to get back the instance URI to allow relationship tracking etc sb.AppendLine(" $" + GetInstanceName()); }
/// <summary> /// Creates the where clause of the SPARQL query - the part that indicates what the properties of selected objects should be. /// </summary> /// <param name="sb">A <see cref="StringBuilder"/> into which the SPARQL should be inserted.</param> private void CreateWhereClause(StringBuilder sb) { // if using an identity projection then every available property of the type must be returned bool isIdentityProjection = OriginalType == typeof(T); // if there is no where clause then we want every instance back (and we won't be filtering) // the logic around this is a little tricky (or debatable) - // Given that you could have instances that are partially complete in the triple store (i.e. not all triples are present) // you need to be able to ensure that a query that does not explicitly include the missing properties does not // exclude any instances where those properties are missing. // I've reasoned that if you perform an identity projection, then you're saying "get me whatever you can", whereas if // you specifically request a certain property (via a projection) then you really must want a value for that, and thus // instances must be excluded where there is no value _known_ - Hence the '|| IsIdentityProjection'. bool getAnythingThatYouCan = !(Expressions.ContainsKey("Where")) || isIdentityProjection /* */; // using "$" distinguishes this varName from anything that could be introduced from the properties of the type // therefore the varName is 'safe' in the sense that there can never be a name clash. string varName = "$" + GetInstanceName(); sb.Append("WHERE {\n"); // if parameters have been defined somewhere. If using an identity projection then we will not be getting anything from projectionParameters // if we have no WHERE expression, then we also won't be getting anything from queryGraphParameters var parameters = new List <MemberInfo>(QueryGraphParameters.Union(ProjectionParameters)); if (parameters.Count == 0) { // is it an identity projection? If so, place all persistent properties into parameters if (isIdentityProjection) { foreach (PropertyInfo info in OwlClassSupertype.GetAllPersistentProperties(OriginalType)) { parameters.Add(info); } } } // if (parameters.Count > 0) // { sb.AppendFormat("{0} a {1}:{2} .\n", varName, OriginalType.GetOntology().Prefix, OriginalType.GetOwlResource().RelativeUriReference); // } // else // { // // I don't think there is any way to get into to this point unless the object is persistent, but has no // throw new ApplicationException( // "No persistent properties defined on the entity. Unable to generate a query."); // } // // temp var to get the object variables list IEnumerable <MemberInfo> args; // a temp string to get the tripleFormat that will be used to generate query triples. string tripleFormat = "OPTIONAL{{{0} {1}:{2} ?{3} .}}\n"; if (!getAnythingThatYouCan) { tripleFormat = "{0} {1}:{2} ?{3} .\n"; } if (isIdentityProjection) { args = OwlClassSupertype.GetAllPersistentProperties(OriginalType); } else { args = parameters; } foreach (MemberInfo arg in args) { // The ontology and prefix assigned to a class property need not match those assigned to the class itself. // e.g. The class could have a property which maps to foaf:name, or dc:title. OwlResourceAttribute ora = arg.GetOwlResource(); sb.AppendFormat(tripleFormat, varName, AttributeExtensions.GetOntologyPrefix(ora.OntologyName), //WAS: originalType.GetOntology().Prefix, ora.RelativeUriReference, arg.Name); } if (!string.IsNullOrEmpty(PropertyReferenceTriple)) { sb.AppendLine(PropertyReferenceTriple); } if (!string.IsNullOrEmpty(FilterClause)) { sb.AppendFormat("FILTER( {0} )\n", FilterClause); } sb.Append("}\n"); }