New e-d-s backend which indexes all local addressbooks and calendars.
[beagle.git] / BeagleClient / Hit.cs
blobfbbcedb885437961f14b6b5d230ea11e699c1462
1 //
2 // Hit.cs
3 //
4 // Copyright (C) 2004 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
28 using System;
29 using System.Collections;
30 using System.Diagnostics;
31 using System.IO;
32 using System.Xml;
33 using System.Xml.Serialization;
35 using Beagle.Util;
37 namespace Beagle {
39 public class Hit: Versioned, IComparable {
41 // A unique ID. id <= 0 means 'undefined'.
42 private int id = 0;
44 // A URI we can use to locate the source of this match.
45 private Uri uri = null;
47 // A URI of this Hit's container element
48 private Uri parent_uri = null;
50 // File, Web, MailMessage, IMLog, etc.
51 private string type = null;
53 // If applicable, otherwise set to null.
54 private string mimeType = null;
56 // IndexUser, IndexSystem, Google, Addressbook, iFolder, etc.
57 private string source = null;
59 // This is used to hold a copy of the Queryable in the
60 // server-side copy of the Hit. It is always null
61 // on the client-side.
62 private object sourceObject = null;
63 private string source_object_name = null;
65 // High scores imply greater relevance.
66 private double scoreRaw = 0.0;
67 private double scoreMultiplier = 1.0;
69 private ArrayList properties = new ArrayList ();
70 private bool sorted = true;
72 private enum SpecialType {
73 Unknown,
74 None,
75 Invalid,
76 File,
77 Directory
80 SpecialType special = SpecialType.Unknown;
82 private string path;
83 private FileInfo fileInfo = null;
84 private DirectoryInfo directoryInfo = null;
86 //////////////////////////
88 [XmlAttribute]
89 public int Id {
90 get { return id; }
91 set { id = value; }
94 [XmlIgnore]
95 public Uri Uri {
96 get { return uri; }
97 set { uri = value; }
100 [XmlAttribute ("Uri")]
101 public string UriAsString {
102 get {
103 return UriFu.UriToSerializableString (uri);
106 set {
107 uri = UriFu.UriStringToUri (value);
111 [XmlIgnore]
112 public Uri ParentUri {
113 get { return parent_uri; }
114 set { parent_uri = value; }
117 [XmlAttribute ("ParentUri")]
118 public string ParentUriAsString {
119 get {
120 if (parent_uri == null)
121 return null;
123 return UriFu.UriToSerializableString (parent_uri);
126 set {
127 if (value == null)
128 parent_uri = null;
129 else
130 parent_uri = UriFu.UriStringToUri (value);
134 [XmlAttribute]
135 public string Type {
136 get { return type; }
137 set { type = value; }
140 [XmlAttribute]
141 public string MimeType {
142 get { return mimeType; }
143 set { mimeType = value; }
146 [XmlAttribute]
147 public string Source {
148 get { return source; }
149 set { source = value; }
152 [XmlIgnore]
153 public object SourceObject {
154 get { return sourceObject; }
155 set { sourceObject = value; }
158 [XmlAttribute]
159 public string SourceObjectName {
160 get { return source_object_name; }
161 set { source_object_name = value; }
164 public double Score {
165 get { return scoreRaw * scoreMultiplier; }
168 [XmlAttribute]
169 public double ScoreRaw {
170 get { return scoreRaw; }
171 set { scoreRaw = value; }
174 [XmlAttribute]
175 public double ScoreMultiplier {
176 get { return scoreMultiplier; }
177 set {
178 scoreMultiplier = value;
179 if (scoreMultiplier < 0) {
180 Logger.Log.Warn ("Invalid ScoreMultiplier={0} for {1}", scoreMultiplier, Uri);
181 scoreMultiplier = 0;
182 } else if (scoreMultiplier > 1) {
183 Logger.Log.Warn ("Invalid ScoreMultiplier={0} for {1}", scoreMultiplier, Uri);
184 scoreMultiplier = 1;
190 //////////////////////////
192 private void SpecialHandling ()
194 if (special != SpecialType.Unknown)
195 return;
197 if (uri.IsFile) {
198 path = uri.LocalPath;
199 if (File.Exists (path))
200 special = SpecialType.File;
201 else if (Directory.Exists (path))
202 special = SpecialType.Directory;
203 else
204 special = SpecialType.Invalid;
207 if (special == SpecialType.Unknown)
208 special = SpecialType.None;
211 public bool IsValid {
212 get { SpecialHandling (); return special != SpecialType.Invalid; }
215 public bool IsFile {
216 get { SpecialHandling (); return special == SpecialType.File; }
219 public bool IsDirectory {
220 get { SpecialHandling (); return special == SpecialType.Directory; }
223 public bool IsFileSystem {
224 get { return IsFile || IsDirectory; }
227 public string Path {
228 get { SpecialHandling (); return path; }
231 public string PathQuoted {
232 get { return Path.Replace (" ", "\\ "); }
235 public string FileName {
236 get { return Path != null ? System.IO.Path.GetFileName (Path) : null; }
239 public string DirectoryName {
240 get { return Path != null ? System.IO.Path.GetDirectoryName (Path) : null; }
243 [XmlIgnore]
244 public FileSystemInfo FileSystemInfo {
245 get {
246 if (IsFile)
247 return (FileSystemInfo) FileInfo;
248 else if (IsDirectory)
249 return (FileSystemInfo) DirectoryInfo;
250 else
251 return null;
255 [XmlIgnore]
256 public FileInfo FileInfo {
257 get {
258 if (fileInfo == null && IsFile)
259 fileInfo = new FileInfo (Path);
260 return fileInfo;
264 [XmlIgnore]
265 public DirectoryInfo DirectoryInfo {
266 get {
267 if (directoryInfo == null && IsDirectory)
268 directoryInfo = new DirectoryInfo (Path);
269 return directoryInfo;
273 //////////////////////////
275 [XmlArray]
276 [XmlArrayItem (ElementName="Property", Type=typeof (Property))]
277 public ArrayList Properties {
278 get { return properties; }
281 public void AddProperty (Property prop)
283 if (sorted && properties.Count > 0) {
284 Property last_prop;
285 last_prop = properties [properties.Count - 1] as Property;
286 if (last_prop.CompareTo (prop) > 0) // i.e. last_prop > prop
287 sorted = false;
290 properties.Add (prop);
293 private bool FindProperty (string key, out int first, out int top)
295 // FIXME: Should use binary search on sorted property list
296 if (! sorted) {
297 properties.Sort ();
298 sorted = true;
301 first = 0;
302 top = 0;
304 while (first < properties.Count) {
305 Property prop;
306 prop = properties [first] as Property;
307 if (prop.Key == key)
308 break;
309 ++first;
312 if (first >= properties.Count)
313 return false;
315 top = first + 1;
316 while (top < properties.Count) {
317 Property prop;
318 prop = properties [top] as Property;
319 if (prop.Key != key)
320 break;
321 ++top;
324 return true;
327 public string this [string key] {
328 get {
329 int first, top;
330 if (! FindProperty (key, out first, out top))
331 return null;
333 if (top - first != 1) {
334 Logger.Log.Debug ("Accessed multi-property key with Hit's indexer.");
335 return null;
338 Property prop;
339 prop = properties [first] as Property;
340 return prop.Value;
343 set {
344 int first = 0, top = 0;
346 // If we've never heard of this property, add it.
347 if (! FindProperty (key, out first, out top)) {
348 AddProperty (Property.New (key, value));
349 return;
352 // If it has appeared once before, clobber the existing
353 // value. This emulates the previous (broken) semantics.
355 if (top - first == 1) {
356 properties [first] = Property.New (key, value);
357 return;
360 // Otherwise throw an exception (which sort of sucks,
361 // but we don't really know what to do there)
362 throw new Exception (String.Format ("Attempt to re-set multi-property '{0}' via the indexer", key));
366 public string[] GetProperties (string key)
368 int first, top;
369 if (! FindProperty (key, out first, out top))
370 return null;
372 string[] values = new string [top - first];
374 for (int i = 0; first + i < top; i++) {
375 Property prop = properties [first + i] as Property;
376 values [i] = prop.Value;
379 return values;
382 //////////////////////////
384 public override int GetHashCode ()
386 return (uri != null ? uri.ToString().GetHashCode () : 0)
387 ^ (type != null ? type.GetHashCode () : 0)
388 ^ (source != null ? source.GetHashCode () : 0);
391 //////////////////////////
393 public int CompareTo (object obj)
395 Hit otherHit = (Hit) obj;
396 // Notice that we sort from high to low.
397 return otherHit.Score.CompareTo (this.Score);