/**
  * Removes a specific <tt>UserCapsNodeListener</tt> from the list of
  * <tt>UserCapsNodeListener</tt>s interested in events notifying about changes in the list of user
  * caps nodes of this <tt>EntityCapsManager</tt>.
  *
  * @param listener the <tt>UserCapsNodeListener</tt> which is no longer interested in events
  *     notifying about changes in the list of user caps nodes of this <tt>EntityCapsManager</tt>
  */
 public void removeUserCapsNodeListener(UserCapsNodeListener listener) {
   if (listener != null) {
     synchronized (userCapsNodeListeners) {
       userCapsNodeListeners.remove(listener);
     }
   }
 }
  /**
   * Remove records telling what entity caps node a contact has.
   *
   * @param contact the contact
   */
  public void removeContactCapsNode(Contact contact) {
    Caps caps = null;
    String lastRemovedJid = null;

    Iterator<String> iter = userCaps.keySet().iterator();
    while (iter.hasNext()) {
      String jid = iter.next();

      if (StringUtils.parseBareAddress(jid).equals(contact.getAddress())) {
        caps = userCaps.get(jid);
        lastRemovedJid = jid;
        iter.remove();
      }
    }

    // fire only for the last one, at the end the event out
    // of the protocol will be one and for the contact
    if (caps != null) {
      UserCapsNodeListener[] listeners;
      synchronized (userCapsNodeListeners) {
        listeners = userCapsNodeListeners.toArray(NO_USER_CAPS_NODE_LISTENERS);
      }
      if (listeners.length != 0) {
        String nodeVer = caps.getNodeVer();

        for (UserCapsNodeListener listener : listeners)
          listener.userCapsNodeRemoved(lastRemovedJid, nodeVer, false);
      }
    }
  }
  /**
   * Add a record telling what entity caps node a user has.
   *
   * @param user the user (Full JID)
   * @param node the node (of the caps packet extension)
   * @param hash the hashing algorithm used to calculate <tt>ver</tt>
   * @param ver the version (of the caps packet extension)
   * @param ext the ext (of the caps packet extension)
   * @param online indicates if the user is online
   */
  private void addUserCapsNode(
      String user, String node, String hash, String ver, String ext, boolean online) {
    if ((user != null) && (node != null) && (hash != null) && (ver != null)) {
      Caps caps = userCaps.get(user);

      if ((caps == null)
          || !caps.node.equals(node)
          || !caps.hash.equals(hash)
          || !caps.ver.equals(ver)) {
        caps = new Caps(node, hash, ver, ext);

        userCaps.put(user, caps);
      } else return;

      // Fire userCapsNodeAdded.
      UserCapsNodeListener[] listeners;

      synchronized (userCapsNodeListeners) {
        listeners = userCapsNodeListeners.toArray(NO_USER_CAPS_NODE_LISTENERS);
      }
      if (listeners.length != 0) {
        String nodeVer = caps.getNodeVer();

        for (UserCapsNodeListener listener : listeners)
          listener.userCapsNodeAdded(user, nodeVer, online);
      }
    }
  }
  /**
   * Remove a record telling what entity caps node a user has.
   *
   * @param user the user (Full JID)
   */
  public void removeUserCapsNode(String user) {
    Caps caps = userCaps.remove(user);

    // Fire userCapsNodeRemoved.
    if (caps != null) {
      UserCapsNodeListener[] listeners;

      synchronized (userCapsNodeListeners) {
        listeners = userCapsNodeListeners.toArray(NO_USER_CAPS_NODE_LISTENERS);
      }
      if (listeners.length != 0) {
        String nodeVer = caps.getNodeVer();

        for (UserCapsNodeListener listener : listeners)
          listener.userCapsNodeRemoved(user, nodeVer, false);
      }
    }
  }
 /**
  * Adds a specific <tt>UserCapsNodeListener</tt> to the list of <tt>UserCapsNodeListener</tt>s
  * interested in events notifying about changes in the list of user caps nodes of this
  * <tt>EntityCapsManager</tt>.
  *
  * @param listener the <tt>UserCapsNodeListener</tt> which is interested in events notifying about
  *     changes in the list of user caps nodes of this <tt>EntityCapsManager</tt>
  */
 public void addUserCapsNodeListener(UserCapsNodeListener listener) {
   if (listener == null) throw new NullPointerException("listener");
   synchronized (userCapsNodeListeners) {
     if (!userCapsNodeListeners.contains(listener)) userCapsNodeListeners.add(listener);
   }
 }