4 // Copyright (C) 2004 Novell, Inc.
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.
29 using System
.Collections
;
30 using System
.Diagnostics
;
33 using System
.Xml
.Serialization
;
39 public class Hit
: Versioned
, IComparable
{
41 // A URI we can use to locate the source of this match.
42 private Uri uri
= null;
44 // A URI of this Hit's container element
45 private Uri parent_uri
= null;
47 // File, Web, MailMessage, IMLog, etc.
48 private string type
= null;
50 // If applicable, otherwise set to null.
51 private string mimeType
= null;
53 // IndexUser, IndexSystem, Google, Addressbook, iFolder, etc.
54 private string source
= null;
56 // This is used to hold a copy of the Queryable in the
57 // server-side copy of the Hit. It is always null
58 // on the client-side.
59 private object sourceObject
= null;
60 private string source_object_name
= null;
62 // High scores imply greater relevance.
63 private double score
= 0.0;
65 private ArrayList properties
= new ArrayList ();
66 private bool sorted
= true;
68 private enum SpecialType
{
76 SpecialType special
= SpecialType
.Unknown
;
79 private FileInfo fileInfo
= null;
80 private DirectoryInfo directoryInfo
= null;
82 //////////////////////////
90 [XmlAttribute ("Uri")]
91 public string UriAsString
{
93 return UriFu
.UriToSerializableString (uri
);
97 uri
= UriFu
.UriStringToUri (value);
102 public Uri ParentUri
{
103 get { return parent_uri; }
104 set { parent_uri = value; }
107 [XmlAttribute ("ParentUri")]
108 public string ParentUriAsString
{
110 if (parent_uri
== null)
113 return UriFu
.UriToSerializableString (parent_uri
);
120 parent_uri
= UriFu
.UriStringToUri (value);
124 // DEPRECATED: This is now stored as a property.
128 set { type = value; }
131 // DEPRECATED: This is now stored as a property.
133 public string MimeType
{
134 get { return mimeType; }
135 set { mimeType = value; }
139 public string Source
{
140 get { return source; }
141 set { source = value; }
145 public object SourceObject
{
146 get { return sourceObject; }
147 set { sourceObject = value; }
151 public string SourceObjectName
{
152 get { return source_object_name; }
153 set { source_object_name = value; }
157 public double Score
{
158 get { return score; }
159 set { score = value; }
162 //////////////////////////
164 private void SpecialHandling ()
166 if (special
!= SpecialType
.Unknown
)
170 path
= uri
.LocalPath
;
171 if (File
.Exists (path
))
172 special
= SpecialType
.File
;
173 else if (Directory
.Exists (path
))
174 special
= SpecialType
.Directory
;
176 special
= SpecialType
.Invalid
;
179 if (special
== SpecialType
.Unknown
)
180 special
= SpecialType
.None
;
183 public bool IsValid
{
184 get { SpecialHandling (); return special != SpecialType.Invalid; }
188 get { SpecialHandling (); return special == SpecialType.File; }
191 public bool IsDirectory
{
192 get { SpecialHandling (); return special == SpecialType.Directory; }
195 public bool IsFileSystem
{
196 get { return IsFile || IsDirectory; }
200 get { SpecialHandling (); return path; }
203 public string PathQuoted
{
204 get { return Path.Replace (" ", "\\ "); }
207 public string FileName
{
208 get { return Path != null ? System.IO.Path.GetFileName (Path) : null; }
211 public string DirectoryName
{
212 get { return Path != null ? System.IO.Path.GetDirectoryName (Path) : null; }
216 public FileSystemInfo FileSystemInfo
{
219 return (FileSystemInfo
) FileInfo
;
220 else if (IsDirectory
)
221 return (FileSystemInfo
) DirectoryInfo
;
228 public FileInfo FileInfo
{
230 if (fileInfo
== null && IsFile
)
231 fileInfo
= new FileInfo (Path
);
237 public DirectoryInfo DirectoryInfo
{
239 if (directoryInfo
== null && IsDirectory
)
240 directoryInfo
= new DirectoryInfo (Path
);
241 return directoryInfo
;
245 //////////////////////////
248 [XmlArrayItem (ElementName
="Property", Type
=typeof (Property
))]
249 public ArrayList Properties
{
250 get { return properties; }
253 public void AddProperty (Property prop
)
255 if (sorted
&& properties
.Count
> 0) {
257 last_prop
= properties
[properties
.Count
- 1] as Property
;
258 if (last_prop
.CompareTo (prop
) > 0) // i.e. last_prop > prop
262 properties
.Add (prop
);
265 private bool FindProperty (string key
, out int first
, out int top
)
267 // FIXME: Should use binary search on sorted property list
276 while (first
< properties
.Count
) {
278 prop
= properties
[first
] as Property
;
284 if (first
>= properties
.Count
)
288 while (top
< properties
.Count
) {
290 prop
= properties
[top
] as Property
;
299 public string this [string key
] {
302 if (! FindProperty (key
, out first
, out top
))
305 if (top
- first
!= 1) {
306 Logger
.Log
.Debug ("Accessed multi-property key with Hit's indexer.");
311 prop
= properties
[first
] as Property
;
316 int first
= 0, top
= 0;
318 // If we've never heard of this property, add it.
319 if (! FindProperty (key
, out first
, out top
)) {
320 AddProperty (Property
.New (key
, value));
324 // If it has appeared once before, clobber the existing
325 // value. This emulates the previous (broken) semantics.
327 if (top
- first
== 1) {
328 properties
[first
] = Property
.New (key
, value);
332 // Otherwise throw an exception (which sort of sucks,
333 // but we don't really know what to do there)
334 throw new Exception (String
.Format ("Attempt to re-set multi-property '{0}' via the indexer", key
));
338 public string GetFirstProperty (string key
)
341 if (! FindProperty (key
, out first
, out top
))
344 prop
= properties
[first
] as Property
;
348 public string[] GetProperties (string key
)
351 if (! FindProperty (key
, out first
, out top
))
354 string[] values
= new string [top
- first
];
356 for (int i
= 0; first
+ i
< top
; i
++) {
357 Property prop
= properties
[first
+ i
] as Property
;
358 values
[i
] = prop
.Value
;
364 //////////////////////////
366 public override int GetHashCode ()
368 return (uri
!= null ? uri
.ToString().GetHashCode () : 0)
369 ^
(type
!= null ? type
.GetHashCode () : 0)
370 ^
(source
!= null ? source
.GetHashCode () : 0);
373 //////////////////////////
375 public int CompareTo (object obj
)
377 Hit otherHit
= (Hit
) obj
;
378 // Notice that we sort by time from most to least recent
379 return DateTime
.Compare (otherHit
.Timestamp
, this.Timestamp
);