Example #1
0
        static private QueryPart MatchToQueryPart(Match m)
        {
            // Looping over all Matches we have got:
            // m.Groups["pm"]	plus or minus sign
            // m.Groups["key"]	keyname
            // m.Groups["quote"]	quoted string
            // m.Groups["midquote1"] + m.Groups["midquote2"] quoted midway string also represents unquoted string

            string query = m.ToString();
            // Either quote is set or midquote1 and (optionally) midquote2 is set
            string text = m.Groups ["quote"].ToString() + m.Groups ["midquote1"].ToString() + m.Groups ["midquote2"].ToString();
            string key  = m.Groups ["key"].ToString();

            bool IsProhibited = (m.Groups ["pm"].ToString() == "-");


            // check for file extensions
            // if match starts with *. or . and only contains letters we assume it's a file extension
            if (extension_re.Match(text).Success || key.ToLower() == "ext" || key.ToLower() == "extension")
            {
                QueryPart_Property query_part = new QueryPart_Property();

                query_part.Key = Property.FilenameExtensionPropKey;

                if (text.StartsWith("*."))
                {
                    query_part.Value = text.Substring(1).ToLower();
                }
                else if (text.StartsWith("."))
                {
                    query_part.Value = text.ToLower();
                }
                else
                {
                    query_part.Value = "." + text.ToLower();
                }

                query_part.Type  = PropertyType.Keyword;
                query_part.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);

                Logger.Log.Debug("Extension query: {0}", query_part.Value);

                return(query_part);
            }

            if (key == String.Empty)
            {
                Logger.Log.Debug("Parsed query '{0}' as text_query", text);

                return(StringToQueryPart(text, IsProhibited));
            }

            // FIXME: i18n-izing "date"
            if (key == "date")
            {
                try {
                    QueryPart part = DateQueryToQueryPart(text);
                    part.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);
                    return(part);
                } catch (FormatException) {
                    Log.Warn("Could not parse [{0}] as date query. Assuming text.", text);
                    return(StringToQueryPart(text, IsProhibited));
                }
            }

            // FIXME: i18n-izing "uri"
            if (key == "uri")
            {
                try {
                    QueryPart_Uri part = new QueryPart_Uri();
                    part.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);
                    // uri: queries require the raw Uri as present in the index
                    part.Uri = new Uri(text, true);
                    return(part);
                } catch (System.UriFormatException) {
                    Log.Warn("Could not parse [{0}] as uri query. Assuming text.", text);
                    return(StringToQueryPart(text, IsProhibited));
                }
            }

            // Special case
            if (key == "inuri")
            {
                QueryPart_Property inuri_part = new QueryPart_Property();
                inuri_part.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);
                inuri_part.Key   = "inuri";
                inuri_part.Value = text;
                inuri_part.Type  = PropertyType.Keyword;
                Log.Debug("Handing special query 'inuri:{0}'", text);
                return(inuri_part);
            }

            // Non-keyword queries by directly using property names
            // Query of form property:namespace:name=value
            // which is translated to a non-keyword query
            // namespace:name=value
            int pos;

            if (key == "property" && ((pos = text.IndexOf('=')) != -1))
            {
                QueryPart_Property part = new QueryPart_Property();
                part.Key   = text.Substring(0, pos);
                part.Value = text.Substring(pos + 1);
                part.Type  = PropertyType.Text;
                part.Logic = (IsProhibited ?      QueryPartLogic.Prohibited : QueryPartLogic.Required);
                Logger.Log.Debug("Parsed query '" + query +
                                 "' as prop query:key=" + part.Key +
                                 ", value=" + part.Value +
                                 " and property type=" + part.Type);

                return(part);
            }

            // keyword queries by directly using property names
            // Query of form keyword:namespace:name=value
            // which is translated to a keyword query
            // namespace:name=value
            if (key == "keyword" && ((pos = text.IndexOf('=')) != -1))
            {
                QueryPart_Property part = new QueryPart_Property();
                part.Key   = text.Substring(0, pos);
                part.Value = text.Substring(pos + 1);
                part.Type  = PropertyType.Keyword;
                part.Logic = (IsProhibited ?      QueryPartLogic.Prohibited : QueryPartLogic.Required);
                Logger.Log.Debug("Parsed query '" + query +
                                 "' as prop query:key=" + part.Key +
                                 ", value=" + part.Value +
                                 " and property type=" + part.Type);

                return(part);
            }

            string[] prop_string = null;
            bool     is_present;

            PropertyType[] prop_type;
            int            num;

            is_present = PropertyKeywordFu.GetMapping(key, out num, out prop_string, out prop_type);
            // if key is not present in the mapping, assume the query is a text query
            // i.e. if token is foo:bar and there is no mappable property named foo,
            // assume "foo:bar" as text query
            // FIXME the analyzer changes the text query "foo:bar" to "foo bar"
            // which might not be the right thing to do

            if (!is_present)
            {
                Logger.Log.Warn("Could not find property, parsed query '{0}' as text_query", query);

                return(StringToQueryPart(query, IsProhibited));
            }

            if (num == 1)
            {
                QueryPart_Property query_part_prop = new QueryPart_Property();
                query_part_prop.Key   = prop_string [0];
                query_part_prop.Value = text;
                query_part_prop.Type  = prop_type [0];
                query_part_prop.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);

                Logger.Log.Debug("Parsed query '" + query +
                                 "' as prop query:key=" + query_part_prop.Key +
                                 ", value=" + query_part_prop.Value +
                                 " and property type=" + query_part_prop.Type);

                return(query_part_prop);
            }

            // Multiple property queries are mapped to this keyword query
            // Create an OR query from them
            // FIXME: Would anyone want an AND query ?

            QueryPart_Or query_part_or = new QueryPart_Or();

            query_part_or.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);

            Logger.Log.Debug("Parsed query '{0}' as OR of {1} queries:", query, num);

            for (int i = 0; i < num; ++i)
            {
                QueryPart_Property query_part_prop = new QueryPart_Property();
                query_part_prop.Key   = prop_string [i];
                query_part_prop.Value = text;
                query_part_prop.Type  = prop_type [i];
                query_part_prop.Logic = QueryPartLogic.Required;

                Log.Debug("\t:key={0}, value={1} and property type={2}", query_part_prop.Key, query_part_prop.Value, query_part_prop.Type);
                query_part_or.Add(query_part_prop);
            }

            return(query_part_or);
        }
Example #2
0
                static private QueryPart MatchToQueryPart (Match m)
                {
                        // Looping over all Matches we have got:
                        // m.Groups["pm"]       plus or minus sign
                        // m.Groups["key"]      keyname
                        // m.Groups["quote"]    quoted string
                        // m.Groups["midquote1"] + m.Groups["midquote2"] quoted midway string also represents unquoted string

                        string query = m.ToString ();
                        // Either quote is set or midquote1 and (optionally) midquote2 is set
                        string text = m.Groups ["quote"].ToString () + m.Groups ["midquote1"].ToString () + m.Groups ["midquote2"].ToString ();
                        string key = m.Groups ["key"].ToString ();

                        bool IsProhibited = (m.Groups ["pm"].ToString () == "-");


                        // check for file extensions
                        // if match starts with *. or . and only contains letters we assume it's a file extension
                        if (extension_re.Match (text).Success || key.ToLower () == "ext" || key.ToLower () == "extension") {

                                QueryPart_Property query_part = new QueryPart_Property ();

                                query_part.Key = Property.FilenameExtensionPropKey;

                                if (text.StartsWith ("*."))
                                        query_part.Value = text.Substring (1).ToLower ();
                                else if (text.StartsWith ("."))
                                        query_part.Value = text.ToLower ();
                                else
                                        query_part.Value = "." + text.ToLower ();

                                query_part.Type = PropertyType.Keyword;
                                query_part.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);

                                Logger.Log.Debug ("Extension query: {0}", query_part.Value);

                                return query_part;
                        }

                        if (key == String.Empty) {

                                Logger.Log.Debug ("Parsed query '{0}' as text_query", text);

                                return StringToQueryPart (text, IsProhibited);
                        }

                        // FIXME: i18n-izing "date"
                        if (key == "date") {
                                try {
                                        QueryPart part = DateQueryToQueryPart (text);
                                        part.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);
                                        return part;
                                } catch (FormatException) {
                                        Log.Warn ("Could not parse [{0}] as date query. Assuming text.", text);
                                        return StringToQueryPart (text, IsProhibited);
                                }
                        }

                        // FIXME: i18n-izing "uri"
                        if (key == "uri") {
                                try {
                                        QueryPart_Uri part = new QueryPart_Uri ();
                                        part.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);
                                        part.Uri = UriFu.UserUritoEscapedUri (text);
                                        return part;
                                } catch (System.UriFormatException) {
                                        Log.Warn ("Could not parse [{0}] as uri query. Assuming text.", text);
                                        return StringToQueryPart (text, IsProhibited);
                                }
                        }

                        // Special case
                        if (key == "inuri") {
                                QueryPart_Property inuri_part = new QueryPart_Property ();
                                inuri_part.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);
                                inuri_part.Key = "inuri";
                                inuri_part.Value = text;
                                inuri_part.Type = PropertyType.Keyword;
                                Log.Debug ("Handing special query 'inuri:{0}'", text);
                                return inuri_part;
                        }

                        // Non-keyword queries by directly using property names
                        // Query of form property:namespace:name=value
                        // which is translated to a non-keyword query
                        // namespace:name=value
                        int pos;
                        if (key == "property" && ((pos = text.IndexOf ('=')) != -1)) {
                                QueryPart_Property part = new QueryPart_Property ();
                                part.Key = text.Substring (0, pos);
                                part.Value = text.Substring (pos + 1);
                                part.Type = PropertyType.Text;
                                part.Logic = (IsProhibited ?      QueryPartLogic.Prohibited : QueryPartLogic.Required);
                                Logger.Log.Debug ("Parsed query '"          + query +
                                                  "' as prop query:key="    + part.Key +
                                                  ", value="                + part.Value +
                                                  " and property type="     + part.Type);

                                return part;
                        }

                        // keyword queries by directly using property names
                        // Query of form keyword:namespace:name=value
                        // which is translated to a keyword query
                        // namespace:name=value
                        if (key == "keyword" && ((pos = text.IndexOf ('=')) != -1)) {
                                QueryPart_Property part = new QueryPart_Property ();
                                part.Key = text.Substring (0, pos);
                                part.Value = text.Substring (pos + 1);
                                part.Type = PropertyType.Keyword;
                                part.Logic = (IsProhibited ?      QueryPartLogic.Prohibited : QueryPartLogic.Required);
                                Logger.Log.Debug ("Parsed query '"          + query +
                                                  "' as prop query:key="    + part.Key +
                                                  ", value="                + part.Value +
                                                  " and property type="     + part.Type);

                                return part;
                        }

                        if ((pos = text.IndexOf('*')) >= 0) {
                            QueryPart_Wildcard wild = new QueryPart_Wildcard();
                            wild.QueryString = text;
                            wild.PropertyOnly = true;
                            return wild;
                        }

                        string[] prop_string = null;
                        bool is_present;
                        PropertyType[] prop_type;
                        int num;

                        is_present = PropertyKeywordFu.GetMapping (key, out num, out prop_string, out prop_type);
                        // if key is not present in the mapping, assume the query is a text query
                        // i.e. if token is foo:bar and there is no mappable property named foo,
                        // assume "foo:bar" as text query
                        // FIXME the analyzer changes the text query "foo:bar" to "foo bar"
                        // which might not be the right thing to do

                        if (!is_present) {

                                Logger.Log.Warn ("Could not find property, parsed query '{0}' as text_query", query);

                                return StringToQueryPart (query, IsProhibited);
                        }

                        if (num == 1) {
                                QueryPart_Property query_part_prop = new QueryPart_Property ();
                                query_part_prop.Key = prop_string [0];
                                query_part_prop.Value = text;
                                query_part_prop.Type = prop_type [0];
                                query_part_prop.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);

                                Logger.Log.Debug ("Parsed query '"          + query +
                                                  "' as prop query:key="    + query_part_prop.Key +
                                                  ", value="                + query_part_prop.Value +
                                                  " and property type="     + query_part_prop.Type);

                                return query_part_prop;
                        }

                        // Multiple property queries are mapped to this keyword query
                        // Create an OR query from them
                        // FIXME: Would anyone want an AND query ?

                        QueryPart_Or query_part_or = new QueryPart_Or ();
                        query_part_or.Logic = (IsProhibited ? QueryPartLogic.Prohibited : QueryPartLogic.Required);

                        Logger.Log.Debug ("Parsed query '{0}' as OR of {1} queries:", query, num);

                        for (int i = 0; i < num; ++i) {
                                QueryPart_Property query_part_prop = new QueryPart_Property ();
                                query_part_prop.Key = prop_string [i];
                                query_part_prop.Value = text;
                                query_part_prop.Type = prop_type [i];
                                query_part_prop.Logic = QueryPartLogic.Required;

                                Log.Debug ("\t:key={0}, value={1} and property type={2}", query_part_prop.Key, query_part_prop.Value, query_part_prop.Type);
                                query_part_or.Add (query_part_prop);
                        }

                        return query_part_or;
                }
		///////// RDF fu ///////////////////////////////////////////////

		// Returns a collection of Uris
		// HitFilter and UriFilter are ignored for now
		// They will come into play in the final FetchDocument part
		// FIXME: Should RDFQuery do any query mapping using backend_query_part_hook ?
		// I think it should not. QueryPart hooks are for human beings, RDF is for softwares.
		public ICollection DoRDFQuery (Query _query, TextCache text_cache)
		{
			RDFQuery query = (RDFQuery) _query;

			string subject, predicate, _object;
			PropertyType pred_type;

			subject = query.SubjectString;
			predicate = query.Predicate;
			pred_type = query.PredicateType;
			_object = query.Object;

			if (Debug)
				Logger.Log.Debug ("###### {0}: Starting low-level queries '{1}' : '{4}:{2}' = '{3}'", IndexName, subject, predicate, _object, pred_type);

			// ******** 8 cases **********

			// Return all uris
			if (subject == String.Empty && predicate == String.Empty && _object == String.Empty) {
				ICollection hits = GetAllHitsByUri ().Values;
				foreach (Hit hit in hits)
					foreach (Property text_link_property in GetTextLinks (hit.Uri, text_cache))
						hit.AddProperty (text_link_property);
				return hits;
			}

			// Normal query
			if (subject == String.Empty && predicate == String.Empty && _object != String.Empty) {
				QueryPart_Text part = new QueryPart_Text ();
				part.Text = _object;
				part.SearchFullText = false; // We only search properties in RDF query
				query.AddPart (part);
				return DoLowLevelRDFQuery (query, pred_type, predicate, _object, text_cache);
			}

			// Return uris for all documents with this property
			if (subject == String.Empty && predicate != String.Empty && _object == String.Empty) {
				string field_name = PropertyToFieldName (pred_type, predicate);

				QueryPart_Property part = new QueryPart_Property ();
				part.Type = PropertyType.Internal;
				part.Key = "Properties";
				part.Value = field_name;
				query.AddPart (part);

				return DoLowLevelRDFQuery (query, pred_type, predicate, null, text_cache);
			}

			// Property query
			if (subject == String.Empty && predicate != String.Empty && _object != String.Empty) {
				QueryPart_Property part = new QueryPart_Property ();
				part.Type = pred_type;
				part.Key = predicate;
				part.Value = _object;
				query.AddPart (part);
				return DoLowLevelRDFQuery (query, pred_type, predicate, _object, text_cache);
			}

			// Return if the URI exists
			if (subject != String.Empty && predicate == String.Empty && _object == String.Empty) {
				QueryPart_Uri part = new QueryPart_Uri ();
				part.Uri = new Uri (subject, true); // better be URI!
				query.AddPart (part);
				// FIXME: Which properties to return in the hit? All or none ?
				return DoLowLevelRDFQuery (query, pred_type, predicate, null, text_cache);
			}

			// Normal query in the document with this URI
			if (subject != String.Empty && predicate == String.Empty && _object != String.Empty) {
				QueryPart_Uri uri_part = new QueryPart_Uri ();
				uri_part.Uri = new Uri (subject, true); // better be URI!
				query.AddPart (uri_part);

				QueryPart_Text part = new QueryPart_Text ();
				part.Text = _object;
				part.SearchFullText = false; // We only search properties in RDF query
				query.AddPart (part);

				return DoLowLevelRDFQuery (query, pred_type, predicate, _object, text_cache);
			}

			// Return URI if the document with this URI contains this property
			if (subject != String.Empty && predicate != String.Empty && _object == String.Empty) {
				ArrayList returned_uris = new ArrayList (1);

				ArrayList uri_list = new ArrayList (1);
				uri_list.Add (new Uri (subject, true));

				string field_name = PropertyToFieldName (pred_type, predicate);
				FieldSelector fields = new MapFieldSelector (new string[] { "Uri", "Timestamp", field_name });
				ICollection hits = GetHitsForUris (uri_list, fields);
				if (predicate == "TextLinks") {
					foreach (Hit hit in hits)
						foreach (Property text_link_property in GetTextLinks (hit.Uri, text_cache))
							hit.AddProperty (text_link_property);
				}

				return hits;
			}

			// Property query in the document with this URI
			if (subject != String.Empty && predicate != String.Empty && _object != String.Empty) {
				QueryPart_Uri uri_part = new QueryPart_Uri ();
				uri_part.Uri = new Uri (subject, true); // better be URI!
				query.AddPart (uri_part);

				QueryPart_Property part = new QueryPart_Property ();
				part.Type = pred_type;
				part.Key = predicate;
				part.Value = _object;
				query.AddPart (part);

				return DoLowLevelRDFQuery (query, pred_type, predicate, _object, text_cache);
			}

			throw new Exception ("Never reaches");
		}
		// Remap uri in querypart_uri
		private QueryPart_Uri RemapUriQueryPart (QueryPart_Uri part)
		{
			Uri new_uri = ExternalToInternalUri (part.Uri);
			Log.Debug ("Remapping QueryPart_Uri from {0} to {1}", part.Uri, new_uri);

			// Do the right thing if the uri does not exist
			// Remember QueryPart_Uri can occur inside QueryPart_Or
			if (new_uri == null)
				new_uri = new Uri ("no-match:///"); // Will never match

			QueryPart_Uri new_part = new QueryPart_Uri ();
			new_part.Uri = new_uri;
			new_part.Logic = part.Logic;

			return new_part;
		}