Remove debug spew
[beagle.git] / beagled / EvolutionDataServerQueryable / BookContainer.cs
blob5d673ebf1a464433aaabe589bfd8a3e32cb5beeb
1 //
2 // BookContainer.cs
3 //
4 // Copyright (C) 2005 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.
27 using System;
28 using System.Globalization;
29 using System.IO;
31 using Beagle.Util;
33 using Evolution;
35 namespace Beagle.Daemon.EvolutionDataServerQueryable {
37 public class BookContainer : Container {
39 private Book book;
40 private BookView book_view;
41 private bool ignore_first_batch = false;
42 private Scheduler.Priority priority = Scheduler.Priority.Delayed;
44 public BookContainer (Evolution.Source source, EvolutionDataServerQueryable queryable, string fingerprint) : base (source, queryable, fingerprint) { }
46 public override bool OpenClient ()
48 if (!this.source.IsLocal ()) {
49 Logger.Log.Debug ("Skipping remote addressbook {0}", this.source.Uri);
50 return false;
53 try {
54 this.book = new Book (this.source);
55 this.book.Open (true);
56 } catch (Exception e) {
57 Logger.Log.Warn (e, "Unable to open addressbook {0}:", this.source.Uri);
58 return false;
61 return true;
64 public override void OpenView ()
66 this.book_view = this.book.GetBookView (BookQuery.AnyFieldContains (""),
67 new object [0],
68 -1);
70 this.book_view.ContactsAdded += OnContactsAdded;
71 this.book_view.ContactsRemoved += OnContactsRemoved;
72 this.book_view.ContactsChanged += OnContactsChanged;
73 this.book_view.SequenceComplete += OnSequenceComplete;
75 this.book_view.Start ();
78 public override void IndexAll ()
80 // We don't need to do anything here. All of the
81 // contacts will be added as a result of
82 // OnContactsAdded being called for every item
83 // after setting up the BookView.
86 public override void IndexChanges ()
88 // Ignore the torrent of add events that will come in
89 // after the BookView is set up.
90 ignore_first_batch = true;
92 Contact[] added, changed;
93 string[] removed;
95 Logger.Log.Debug ("Getting addressbook changes for {0}", this.source.Uri);
97 try {
98 this.book.GetChanges ("beagle-" + this.fingerprint, out added, out changed, out removed);
99 } catch (Exception e) {
100 Logger.Log.Warn (e, "Unable to get changes for {0}:", this.source.Uri);
101 return;
104 Logger.Log.Debug ("Addressbook {0}: {1} added, {2} changed, {3} removed",
105 this.book.Uri, added.Length, changed.Length, removed.Length);
107 foreach (Contact contact in added)
108 AddContact (contact);
110 foreach (Contact contact in changed)
111 AddContact (contact);
113 foreach (string id in removed)
114 RemoveContact (id);
117 public override void Remove ()
119 Logger.Log.Debug ("Removing addressbook source {0}", this.source.Uid);
121 Property prop = Property.NewUnsearched ("fixme:source_uid", this.source.Uid);
122 this.queryable.RemovePropertyIndexable (prop);
124 this.book_view.Stop ();
125 this.book_view.Dispose ();
127 this.book.Dispose ();
130 private void OnContactsAdded (object o, Evolution.ContactsAddedArgs args)
132 if (ignore_first_batch)
133 return;
135 foreach (Evolution.Contact contact in args.Contacts)
136 AddContact (contact);
139 private void OnContactsChanged (object o, Evolution.ContactsChangedArgs args)
141 if (ignore_first_batch)
142 return;
144 foreach (Evolution.Contact contact in args.Contacts)
145 AddContact (contact);
148 private void OnContactsRemoved (object o, Evolution.ContactsRemovedArgs args)
150 if (ignore_first_batch)
151 return;
153 // FIXME: This is a temporary workaround for the
154 // fact that the evolution bindings return a
155 // GLib.List with an object type, but there are
156 // really strings in there.
158 GLib.List id_list = new GLib.List (args.Ids.Handle,
159 typeof (string));
161 foreach (string id in id_list)
162 RemoveContact (id);
165 private void OnSequenceComplete (object o, Evolution.SequenceCompleteArgs args)
167 ignore_first_batch = false;
169 // Now that we're done synching with the original
170 // state of the addressbook, switch all new changes to
171 // Immediate mode
172 priority = Scheduler.Priority.Immediate;
174 Logger.Log.Debug ("Sequence complete!");
177 /////////////////////////////////////
179 // URI scheme is:
180 // contacts:///?source-uid=<value>&contact-uid=<value>
182 // The Uri class sucks SO MUCH ASS. It shits itself
183 // on foo:///?bar so we have to insert something in
184 // before "?bar". This is filed as Ximian bug #76146.
185 // Hopefully it is just a bug in Mono and not a
186 // fundamental problem of the Uri class. Fortunately
187 // Evolution can handle the horribly mangled URIs
188 // that come out of it.
190 private Uri GetContactUri (Evolution.Contact contact) {
191 return GetContactUri (contact.Id);
194 private Uri GetContactUri (string id) {
195 return new Uri (String.Format ("contacts://uri-class-sucks/?source-uid={0}&contact-uid={1}",
196 this.source.Uid, id));
199 /////////////////////////////////////
201 private void AddContact (Evolution.Contact contact)
203 Logger.Log.Debug ("We'll index {0}!", contact.FullName);
204 Indexable indexable = ContactToIndexable (contact);
206 this.queryable.AddIndexable (indexable, this.priority);
209 private void RemoveContact (string id)
211 Logger.Log.Debug ("We'll remove {0}", id);
212 this.queryable.RemoveIndexable (GetContactUri (id));
215 /////////////////////////////////////
217 private string GetPhotoFilename (string id)
219 return Path.Combine (this.queryable.PhotoDir, id);
222 private static DateTime RevStringToDateTime (string date_str)
224 if (date_str == null)
225 return DateTime.MinValue;
227 string[] formats = {
228 "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'",
229 "yyyyMMdd'T'HHmmss'Z'"
232 try {
233 return DateTime.ParseExact (date_str, formats,
234 CultureInfo.InvariantCulture,
235 DateTimeStyles.None);
236 } catch (FormatException) {
237 Logger.Log.Warn ("Unable to parse last revision string: {0}", date_str);
238 return DateTime.MinValue;
242 private Indexable ContactToIndexable (Evolution.Contact contact)
244 DateTime rev = RevStringToDateTime (contact.Rev);
246 Indexable indexable = new Indexable (GetContactUri (contact));
247 indexable.Timestamp = rev;
248 indexable.HitType = "Contact";
250 indexable.AddProperty (Property.NewUnsearched ("fixme:source_uid", this.source.Uid));
251 indexable.AddProperty (Property.NewUnsearched ("fixme:uid", contact.Id));
253 indexable.AddProperty (Property.New ("fixme:FileAs", contact.FileAs));
254 indexable.AddProperty (Property.New ("fixme:FullName", contact.FullName));
255 indexable.AddProperty (Property.New ("fixme:GivenName", contact.GivenName));
256 indexable.AddProperty (Property.New ("fixme:FamilyName", contact.FamilyName));
257 indexable.AddProperty (Property.New ("fixme:Nickname", contact.Nickname));
258 indexable.AddProperty (Property.New ("fixme:AddressLabelHome", contact.AddressLabelHome));
259 indexable.AddProperty (Property.New ("fixme:AddressLabelWork", contact.AddressLabelWork));
260 indexable.AddProperty (Property.New ("fixme:AddressLabelOther", contact.AddressLabelOther));
261 indexable.AddProperty (Property.New ("fixme:AssistantPhone", contact.AssistantPhone));
262 indexable.AddProperty (Property.New ("fixme:BusinessPhone", contact.BusinessPhone));
263 indexable.AddProperty (Property.New ("fixme:BusinessPhone2", contact.BusinessPhone2));
264 indexable.AddProperty (Property.New ("fixme:BusinessFax", contact.BusinessFax));
265 indexable.AddProperty (Property.New ("fixme:CallbackPhone", contact.CallbackPhone));
266 indexable.AddProperty (Property.New ("fixme:CarPhone", contact.CarPhone));
267 indexable.AddProperty (Property.New ("fixme:CompanyPhone", contact.CompanyPhone));
268 indexable.AddProperty (Property.New ("fixme:HomePhone", contact.HomePhone));
269 indexable.AddProperty (Property.New ("fixme:HomePhone2", contact.HomePhone2));
270 indexable.AddProperty (Property.New ("fixme:HomeFax", contact.HomeFax));
271 indexable.AddProperty (Property.New ("fixme:IsdnPhone", contact.IsdnPhone));
272 indexable.AddProperty (Property.New ("fixme:MobilePhone", contact.MobilePhone));
273 indexable.AddProperty (Property.New ("fixme:OtherPhone", contact.OtherPhone));
274 indexable.AddProperty (Property.New ("fixme:OtherFax", contact.OtherFax));
275 indexable.AddProperty (Property.New ("fixme:Pager", contact.Pager));
276 indexable.AddProperty (Property.New ("fixme:PrimaryPhone", contact.PrimaryPhone));
277 indexable.AddProperty (Property.New ("fixme:Radio", contact.Radio));
278 indexable.AddProperty (Property.New ("fixme:Telex", contact.Telex));
279 indexable.AddProperty (Property.NewUnsearched ("fixme:Tty", contact.Tty));
280 indexable.AddProperty (Property.NewKeyword ("fixme:Email1", contact.Email1));
281 indexable.AddProperty (Property.NewKeyword ("fixme:Email2", contact.Email2));
282 indexable.AddProperty (Property.NewKeyword ("fixme:Email3", contact.Email3));
283 indexable.AddProperty (Property.NewUnsearched ("fixme:Mailer", contact.Mailer));
284 indexable.AddProperty (Property.New ("fixme:Org", contact.Org));
285 indexable.AddProperty (Property.New ("fixme:OrgUnit", contact.OrgUnit));
286 indexable.AddProperty (Property.New ("fixme:Office", contact.Office));
287 indexable.AddProperty (Property.New ("fixme:Title", contact.Title));
288 indexable.AddProperty (Property.New ("fixme:Role", contact.Role));
289 indexable.AddProperty (Property.New ("fixme:Manager", contact.Manager));
290 indexable.AddProperty (Property.New ("fixme:Assistant", contact.Assistant));
291 indexable.AddProperty (Property.NewKeyword ("fixme:HomepageUrl", contact.HomepageUrl));
292 indexable.AddProperty (Property.NewKeyword ("fixme:BlogUrl", contact.BlogUrl));
293 indexable.AddProperty (Property.NewUnsearched ("fixme:Categories", contact.Categories));
294 indexable.AddProperty (Property.NewUnsearched ("fixme:Caluri", contact.Caluri));
295 indexable.AddProperty (Property.NewUnsearched ("fixme:Icscalendar", contact.Icscalendar));
296 indexable.AddProperty (Property.New ("fixme:Spouse", contact.Spouse));
297 indexable.AddProperty (Property.New ("fixme:Note", contact.Note));
299 Evolution.ContactPhoto photo = contact.Photo;
301 if (photo.Data != null && photo.Data.Length > 0) {
302 string photo_filename = GetPhotoFilename (contact.Id);
303 Stream s = new FileStream (photo_filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
304 BinaryWriter w = new BinaryWriter (s);
305 w.Write (photo.Data);
306 w.Close ();
307 s.Close ();
309 indexable.AddProperty (Property.NewUnsearched ("beagle:Photo", photo_filename));
312 foreach (string im in contact.ImAim)
313 indexable.AddProperty (Property.NewUnsearched ("fixme:ImAim", im));
314 foreach (string im in contact.ImIcq)
315 indexable.AddProperty (Property.NewUnsearched ("fixme:ImIcq", im));
316 foreach (string im in contact.ImJabber)
317 indexable.AddProperty (Property.NewUnsearched ("fixme:ImJabber", im));
318 foreach (string im in contact.ImMsn)
319 indexable.AddProperty (Property.NewUnsearched ("fixme:ImMsn", im));
320 foreach (string im in contact.ImYahoo)
321 indexable.AddProperty (Property.NewUnsearched ("fixme:ImYahoo", im));
322 foreach (string im in contact.ImGroupwise)
323 indexable.AddProperty (Property.NewUnsearched ("fixme:ImGroupwise", im));
325 String name = "";
326 if (contact.GivenName != null && contact.GivenName != "")
327 name = contact.GivenName;
328 if (contact.FamilyName != null && contact.FamilyName != "")
329 name += " " + contact.FamilyName;
330 if (name.Length > 0)
331 indexable.AddProperty (Property.New ("fixme:Name", name));
333 if (contact.Email1 != null)
334 indexable.AddProperty (Property.NewKeyword ("fixme:Email",
335 contact.Email1));
336 return indexable;