UserSearch.java

  1. /**
  2.  *
  3.  * Copyright 2003-2007 Jive Software.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smackx.search;

  18. import org.jivesoftware.smack.SmackException.NoResponseException;
  19. import org.jivesoftware.smack.SmackException.NotConnectedException;
  20. import org.jivesoftware.smack.XMPPConnection;
  21. import org.jivesoftware.smack.XMPPException.XMPPErrorException;
  22. import org.jivesoftware.smack.packet.IQ;
  23. import org.jivesoftware.smack.packet.SimpleIQ;
  24. import org.jivesoftware.smack.provider.IQProvider;
  25. import org.jivesoftware.smack.util.PacketParserUtils;
  26. import org.jivesoftware.smackx.xdata.Form;
  27. import org.jivesoftware.smackx.xdata.FormField;
  28. import org.jivesoftware.smackx.xdata.packet.DataForm;
  29. import org.jxmpp.jid.DomainBareJid;
  30. import org.xmlpull.v1.XmlPullParser;

  31. /**
  32.  * Implements the protocol currently used to search information repositories on the Jabber network. To date, the jabber:iq:search protocol
  33.  * has been used mainly to search for people who have registered with user directories (e.g., the "Jabber User Directory" hosted at users.jabber.org).
  34.  * However, the jabber:iq:search protocol is not limited to user directories, and could be used to search other Jabber information repositories
  35.  * (such as chatroom directories) or even to provide a Jabber interface to conventional search engines.
  36.  * <p/>
  37.  * The basic functionality is to query an information repository regarding the possible search fields, to send a search query, and to receive search results.
  38.  *
  39.  * @author Derek DeMoro
  40.  */
  41. public class UserSearch extends SimpleIQ {

  42.     public static final String ELEMENT = QUERY_ELEMENT;
  43.     public static final String NAMESPACE = "jabber:iq:search";

  44.     /**
  45.      * Creates a new instance of UserSearch.
  46.      */
  47.     public UserSearch() {
  48.         super(ELEMENT, NAMESPACE);
  49.     }

  50.     /**
  51.      * Returns the form for all search fields supported by the search service.
  52.      *
  53.      * @param con           the current XMPPConnection.
  54.      * @param searchService the search service to use. (ex. search.jivesoftware.com)
  55.      * @return the search form received by the server.
  56.      * @throws XMPPErrorException
  57.      * @throws NoResponseException
  58.      * @throws NotConnectedException
  59.      * @throws InterruptedException
  60.      */
  61.     public Form getSearchForm(XMPPConnection con, DomainBareJid searchService) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
  62.         UserSearch search = new UserSearch();
  63.         search.setType(IQ.Type.get);
  64.         search.setTo(searchService);

  65.         IQ response = (IQ) con.createPacketCollectorAndSend(search).nextResultOrThrow();
  66.         return Form.getFormFrom(response);
  67.     }

  68.     /**
  69.      * Sends the filled out answer form to be sent and queried by the search service.
  70.      *
  71.      * @param con           the current XMPPConnection.
  72.      * @param searchForm    the <code>Form</code> to send for querying.
  73.      * @param searchService the search service to use. (ex. search.jivesoftware.com)
  74.      * @return ReportedData the data found from the query.
  75.      * @throws XMPPErrorException
  76.      * @throws NoResponseException
  77.      * @throws NotConnectedException
  78.      * @throws InterruptedException
  79.      */
  80.     public ReportedData sendSearchForm(XMPPConnection con, Form searchForm, DomainBareJid searchService) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
  81.         UserSearch search = new UserSearch();
  82.         search.setType(IQ.Type.set);
  83.         search.setTo(searchService);
  84.         search.addExtension(searchForm.getDataFormToSend());

  85.         IQ response = (IQ) con.createPacketCollectorAndSend(search).nextResultOrThrow();
  86.         return ReportedData.getReportedDataFrom(response);
  87.     }

  88.     /**
  89.      * Sends the filled out answer form to be sent and queried by the search service.
  90.      *
  91.      * @param con           the current XMPPConnection.
  92.      * @param searchForm    the <code>Form</code> to send for querying.
  93.      * @param searchService the search service to use. (ex. search.jivesoftware.com)
  94.      * @return ReportedData the data found from the query.
  95.      * @throws XMPPErrorException
  96.      * @throws NoResponseException
  97.      * @throws NotConnectedException
  98.      * @throws InterruptedException
  99.      */
  100.     public ReportedData sendSimpleSearchForm(XMPPConnection con, Form searchForm, DomainBareJid searchService) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
  101.         SimpleUserSearch search = new SimpleUserSearch();
  102.         search.setForm(searchForm);
  103.         search.setType(IQ.Type.set);
  104.         search.setTo(searchService);

  105.         SimpleUserSearch response = (SimpleUserSearch) con.createPacketCollectorAndSend(search).nextResultOrThrow();
  106.         return response.getReportedData();
  107.     }

  108.     /**
  109.      * Internal Search service Provider.
  110.      */
  111.     public static class Provider extends IQProvider<IQ> {

  112.         // FIXME this provider does return two different types of IQs
  113.         @Override
  114.         public IQ parse(XmlPullParser parser, int initialDepth) throws Exception {
  115.             UserSearch search = null;
  116.             SimpleUserSearch simpleUserSearch = new SimpleUserSearch();

  117.             boolean done = false;
  118.             while (!done) {
  119.                 int eventType = parser.next();
  120.                 if (eventType == XmlPullParser.START_TAG && parser.getName().equals("instructions")) {
  121.                     buildDataForm(simpleUserSearch, parser.nextText(), parser);
  122.                     return simpleUserSearch;
  123.                 }
  124.                 else if (eventType == XmlPullParser.START_TAG && parser.getName().equals("item")) {
  125.                     simpleUserSearch.parseItems(parser);
  126.                     return simpleUserSearch;
  127.                 }
  128.                 else if (eventType == XmlPullParser.START_TAG && parser.getNamespace().equals("jabber:x:data")) {
  129.                     // Otherwise, it must be a packet extension.
  130.                     search = new UserSearch();
  131.                     PacketParserUtils.addExtensionElement(search, parser);
  132.                 }
  133.                 else if (eventType == XmlPullParser.END_TAG) {
  134.                     if (parser.getName().equals("query")) {
  135.                         done = true;
  136.                     }
  137.                 }
  138.             }

  139.             if (search != null) {
  140.                 return search;
  141.             }
  142.             return simpleUserSearch;
  143.         }
  144.     }

  145.     private static void buildDataForm(SimpleUserSearch search,
  146.                     String instructions, XmlPullParser parser)
  147.                     throws Exception {
  148.         DataForm dataForm = new DataForm(DataForm.Type.form);
  149.         boolean done = false;
  150.         dataForm.setTitle("User Search");
  151.         dataForm.addInstruction(instructions);
  152.         while (!done) {
  153.             int eventType = parser.next();

  154.             if (eventType == XmlPullParser.START_TAG && !parser.getNamespace().equals("jabber:x:data")) {
  155.                 String name = parser.getName();
  156.                 FormField field = new FormField(name);

  157.                 // Handle hard coded values.
  158.                 if(name.equals("first")){
  159.                     field.setLabel("First Name");
  160.                 }
  161.                 else if(name.equals("last")){
  162.                     field.setLabel("Last Name");
  163.                 }
  164.                 else if(name.equals("email")){
  165.                     field.setLabel("Email Address");
  166.                 }
  167.                 else if(name.equals("nick")){
  168.                     field.setLabel("Nickname");
  169.                 }

  170.                 field.setType(FormField.Type.text_single);
  171.                 dataForm.addField(field);
  172.             }
  173.             else if (eventType == XmlPullParser.END_TAG) {
  174.                 if (parser.getName().equals("query")) {
  175.                     done = true;
  176.                 }
  177.             }
  178.             else if (eventType == XmlPullParser.START_TAG && parser.getNamespace().equals("jabber:x:data")) {
  179.                 PacketParserUtils.addExtensionElement(search, parser);
  180.                 done = true;
  181.             }
  182.         }
  183.         if (search.getExtension("x", "jabber:x:data") == null) {
  184.             search.addExtension(dataForm);
  185.         }
  186.     }


  187. }