Una classe proxy per consumare Google Desktop Search

Dopo che ho installato il Google Desktop Search,  mi sono interessato per trovare sistemi per interoperare programmaticamente con il servizio come accade per quello online. Google Desktop Search non espone un web service classico/standard ma semplicemente aggiungendo il parametro format=xml alla richiesta verrà tornato il risulato in formato xml... ahimè non esiste/non è stato distribuito uno schema di questo xml :( Leggendo la documentazione, facendo qualche prova empirica e grazie all'uso del fedele xsd.exe ho provato a ricavarne una veloce classe proxy.

Prima cosa la definizione dello schema dati per la deserializzazione dello stream xml. La descrizione delle varie voci/campi delle strutture sono ben descritte nelle documentazione disponibile scaricando l'SDK del servizio.

[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public class results 
{
 [System.Xml.Serialization.XmlElementAttribute("result", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public resultsResult[] result;
 [System.Xml.Serialization.XmlAttributeAttribute()]
 public string count;
}
public class resultsResult 
{
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string category;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string id;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string title;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string url;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string time;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string icon;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string thumbnail;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string cache_url;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string from;
 [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
 public string snippet;
}

Bene il prossimo punto è la definizione della classe proxy. Il servzio di ricerca risponde ad una semplice richiesta HTTP per cui un WebClient andrà più che bene per quello che dovremo fare. La nostra classe proxy avrà una prima parte di inizializzazione (userò il costruttore) dove si andrà a recuperare l'url del servizio comprensivo di token di chiamata. Tale informazione è salvata nel regsitro. La classe avrà poi un metodo Search. Tale metodo accetta come parametri la stringa da cercare, l'indice e il numero massimo di record. Il metodo torna un object e attualmente faccio tornare l'oggetto deserializzato AS IS... L'idea da cui è partito il tutto è quella di creare un aggregatore di ricerche per cui andrebbe pensata una normalizzazione dei dati di ritorno. Stò anche indagando sull'uso del parametro flag (che sembra non essere documentato) che filtra la ricerca per tipologia (mail, file, web etc...).

public class GoogleDesktopSearchService
{
 string searchUrl; 
 XmlSerializer resultSerializer;
 public GoogleDesktopSearchService()
 {
  #region search_url 
  //Note that these requests only do a desktop search, not both a web and desktop search. 
  //The search query URL, including your security token, is stored in the registry at:
  //HKEY_CURRENT_USER\Software\Google\Google Desktop\API\search_url
  using(RegistryKey softareKey = Registry.CurrentUser.OpenSubKey("Software"))
  {
   using(RegistryKey googleKey = softareKey.OpenSubKey("Google"))
   {
    using(RegistryKey googleDesktopKey = googleKey.OpenSubKey("Google Desktop"))
    {
     using(RegistryKey apiKey = googleDesktopKey.OpenSubKey("API"))
     {
      searchUrl = (string)apiKey.GetValue("search_url");
     }
    }
   }
  }
  #endregion
  resultSerializer = new XmlSerializer(typeof(results));
 }

 public object Search(string s, int start, int number)
 {
  StringBuilder searchReqUrl = new StringBuilder(searchUrl);
  searchReqUrl.Append(HttpUtility.UrlEncode(s));
  searchReqUrl.Append("&start=");
  searchReqUrl.Append(start.ToString());
  searchReqUrl.Append("&num=");
  searchReqUrl.Append(number.ToString());
  searchReqUrl.Append("&format=xml");
   
  WebClient web = new WebClient();
  results result;
  using(Stream stream = web.OpenRead(searchReqUrl.ToString()))
  {
   result = (results) resultSerializer.Deserialize(stream);
   stream.Close();
  }
  return result;
 }
}

Mi raccomando! non dimentichiamoci di fare il testing! ;-p

[TestFixture]
public class GoogleDesktopSearchServiceTest
{
 [Test]
 public void SampleSearch()
 {
  string s = "Esempio ricerca";
  int start = 1;
  int number = 10;
  GoogleDesktopSearchService service = new GoogleDesktopSearchService();
  object searchResult = service.Search(s, start, number);
  Assert.IsNotNull(searchResult, "Search result must not be null");   
 }
}

Buona interop a tutti! :-D

posted @ mercoledì 26 ottobre 2005 12:25

Print
Comments have been closed on this topic.
«aprile»
domlunmarmergiovensab
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011