/// <summary> /// Tries to create property functions. /// </summary> /// <param name="info">Function information.</param> /// <param name="function">Property Function.</param> /// <returns></returns> public bool TryCreatePropertyFunction(PropertyFunctionInfo info, out IPropertyFunctionPattern function) { function = null; switch (info.FunctionUri.AbsoluteUri) { case FullTextHelper.FullTextMatchPredicateUri: function = new PropertyFunctionPattern(info, new FullTextMatchPropertyFunction(info)); return(true); default: return(false); } }
/// <summary> /// Tries to create a property function /// </summary> /// <param name="info">Property Function information</param> /// <param name="localFactories">Locally Scoped factories</param> /// <param name="function">Property Function</param> /// <returns></returns> public static bool TryCreatePropertyFunction(PropertyFunctionInfo info, IEnumerable <IPropertyFunctionFactory> localFactories, out IPropertyFunctionPattern function) { function = null; // First try locally scoped factories foreach (IPropertyFunctionFactory factory in localFactories) { if (factory.TryCreatePropertyFunction(info, out function)) { return(true); } } // Then try global factories foreach (IPropertyFunctionFactory factory in _factories) { if (factory.TryCreatePropertyFunction(info, out function)) { return(true); } } return(false); }
/// <summary> /// Used to extract the patterns that make up property functions. /// </summary> /// <param name="patterns">Triple Patterns.</param> /// <param name="localFactories">Locally scoped factories.</param> /// <returns></returns> public static List <IPropertyFunctionPattern> ExtractPatterns(IEnumerable <ITriplePattern> patterns, IEnumerable <IPropertyFunctionFactory> localFactories) { // Do a first pass which simply looks to find any 'magic' properties Dictionary <PatternItem, PropertyFunctionInfo> funcInfo = new Dictionary <PatternItem, PropertyFunctionInfo>(); List <IMatchTriplePattern> ps = patterns.OfType <IMatchTriplePattern>().ToList(); if (ps.Count == 0) { return(new List <IPropertyFunctionPattern>()); } foreach (IMatchTriplePattern tp in ps) { NodeMatchPattern predItem = tp.Predicate as NodeMatchPattern; if (predItem == null) { continue; } IUriNode predNode = predItem.Node as IUriNode; if (predNode == null) { continue; } if (PropertyFunctionFactory.IsPropertyFunction(predNode.Uri, localFactories)) { PropertyFunctionInfo info = new PropertyFunctionInfo(predNode.Uri); info.Patterns.Add(tp); funcInfo.Add(tp.Subject, info); } } // Remove any Patterns we found from the original patterns foreach (PropertyFunctionInfo info in funcInfo.Values) { info.Patterns.ForEach(tp => ps.Remove(tp)); } if (funcInfo.Count == 0) { return(new List <IPropertyFunctionPattern>()); } // Now for each 'magic' property we found do a further search to see if we are using // the collection forms to provide extended arguments foreach (PatternItem key in funcInfo.Keys) { if (key.VariableName != null && key.VariableName.StartsWith("_:")) { // If LHS is a blank node may be collection form int count = funcInfo[key].Patterns.Count; ExtractRelatedPatterns(key, key, ps, funcInfo, funcInfo[key].SubjectArgs); if (funcInfo[key].Patterns.Count == count) { // If no further patterns found just single LHS argument funcInfo[key].SubjectArgs.Add(key); } } else { // Otherwise key is the only LHS argument funcInfo[key].SubjectArgs.Add(key); } PatternItem searchKey = funcInfo[key].Patterns.First().Object; if (searchKey.VariableName != null && searchKey.VariableName.StartsWith("_:")) { // If RHS is a blank node may be collection form int count = funcInfo[key].Patterns.Count; ExtractRelatedPatterns(key, searchKey, ps, funcInfo, funcInfo[key].ObjectArgs); if (funcInfo[key].Patterns.Count == count) { // If no further patterns found just single RHS argument funcInfo[key].ObjectArgs.Add(searchKey); } } else { // Otherwise single RHS argument funcInfo[key].ObjectArgs.Add(searchKey); } } // Now try to create actual property functions List <IPropertyFunctionPattern> propFunctions = new List <IPropertyFunctionPattern>(); foreach (PatternItem key in funcInfo.Keys) { IPropertyFunctionPattern propFunc; if (PropertyFunctionFactory.TryCreatePropertyFunction(funcInfo[key], localFactories, out propFunc)) { propFunctions.Add(propFunc); } } return(propFunctions); }
/// <summary> /// Constructs a Full Text Match property function /// </summary> /// <param name="info">Property Function information</param> public FullTextMatchPropertyFunction(PropertyFunctionInfo info) { if (info == null) { throw new ArgumentNullException("info"); } if (!EqualityHelper.AreUrisEqual(info.FunctionUri, this.FunctionUri)) { throw new ArgumentException("Property Function information is not valid for this function"); } //Get basic arguments this._matchVar = info.SubjectArgs[0]; if (this._matchVar.VariableName != null) { this._vars.Add(this._matchVar.VariableName); } if (info.SubjectArgs.Count == 2) { this._scoreVar = info.SubjectArgs[1]; if (this._scoreVar.VariableName != null) { this._vars.Add(this._scoreVar.VariableName); } } //Check extended arguments this._searchVar = info.ObjectArgs[0]; if (this._searchVar.VariableName != null) { this._vars.Add(this._searchVar.VariableName); } switch (info.ObjectArgs.Count) { case 1: break; case 2: PatternItem arg = info.ObjectArgs[1]; if (arg.VariableName != null) { throw new RdfQueryException("Cannot use a variable as the limit/score threshold for full text queries, must use a numeric constant"); } IValuedNode n = ((NodeMatchPattern)arg).Node.AsValuedNode(); switch (n.NumericType) { case SparqlNumericType.Integer: this._limit = (int)n.AsInteger(); break; case SparqlNumericType.Decimal: case SparqlNumericType.Double: case SparqlNumericType.Float: this._threshold = n.AsDouble(); break; default: throw new RdfQueryException("Cannot use a non-numeric constant as the limit/score threshold for full text queries, must use a numeric constant"); } break; case 3: default: PatternItem arg1 = info.ObjectArgs[1]; PatternItem arg2 = info.ObjectArgs[2]; if (arg1.VariableName != null || arg2.VariableName != null) { throw new RdfQueryException("Cannot use a variable as the limit/score threshold for full text queries, must use a numeric constant"); } IValuedNode n1 = ((NodeMatchPattern)arg1).Node.AsValuedNode(); switch (n1.NumericType) { case SparqlNumericType.NaN: throw new RdfQueryException("Cannot use a non-numeric constant as the score threshold for full text queries, must use a numeric constant"); default: this._threshold = n1.AsDouble(); break; } IValuedNode n2 = ((NodeMatchPattern)arg2).Node.AsValuedNode(); switch (n2.NumericType) { case SparqlNumericType.NaN: throw new RdfQueryException("Cannot use a non-numeric constant as the limit for full text queries, must use a numeric constant"); default: this._limit = (int)n2.AsInteger(); break; } break; } }
/// <summary> /// Tries to create a property function /// </summary> /// <param name="info">Property Function information</param> /// <param name="function">Property Function</param> /// <returns></returns> public static bool TryCreatePropertyFunction(PropertyFunctionInfo info, out IPropertyFunctionPattern function) { return(TryCreatePropertyFunction(info, Enumerable.Empty <IPropertyFunctionFactory>(), out function)); }