/**
   * Overrides the Behaviour.action() method. This method is executed by the agent thread. It
   * basically defines two sub behaviours, which are in charge of periodically updating the DF and
   * receiving DF notifications.
   */
  public void action() {
    try {
      // first thing to do is to register on the df and save current location if any
      DFAgentDescription myDescription = new DFAgentDescription();
      // fill a msn service description
      ServiceDescription msnServiceDescription = new ServiceDescription();
      msnServiceDescription.setName(MsnAgent.msnDescName);
      msnServiceDescription.setType(MsnAgent.msnDescType);
      myDescription.addServices(msnServiceDescription);

      ContactManager.getInstance().resetModifications();

      DFAgentDescription[] onlineContacts = DFService.search(myAgent, myDescription);

      updateContactList(onlineContacts);

      MsnEvent event = MsnEventMgr.getInstance().createEvent(MsnEvent.VIEW_REFRESH_EVENT);

      Map<String, Contact> cMap = ContactManager.getInstance().getAllContacts();
      Map<String, ContactLocation> cLocMap = ContactManager.getInstance().getAllContactLocations();
      ContactListChanges changes = ContactManager.getInstance().getModifications();

      myLogger.log(
          Logger.FINE,
          "Thread "
              + Thread.currentThread().getId()
              + "After reading local contacts and first df query: "
              + "Adding to VIEW_REFRESH_EVENT this list of changes: "
              + changes.toString());
      event.addParam(MsnEvent.VIEW_REFRESH_PARAM_LISTOFCHANGES, changes);
      event.addParam(MsnEvent.VIEW_REFRESH_CONTACTSMAP, cMap);
      event.addParam(MsnEvent.VIEW_REFRESH_PARAM_LOCATIONMAP, cLocMap);
      MsnEventMgr.getInstance().fireEvent(event);

      DFUpdaterBehaviour updater =
          new DFUpdaterBehaviour(myAgent, msnUpdateTime, myContactLocation);
      MsnAgent agent = (MsnAgent) myAgent;
      DFSubscriptionBehaviour subBh =
          new DFSubscriptionBehaviour(myAgent, agent.getSubscriptionMessage());

      myAgent.addBehaviour(updater);
      myAgent.addBehaviour(subBh);
    } catch (Exception e) {
      // TODO Auto-generated catch block
      myLogger.log(Logger.SEVERE, "Severe error: ", e);
      e.printStackTrace();
    }
  }
    /**
     * Overrides SubscriptionInitiator.handleInform(), defining what to do each time the DF is
     * modified by a contact Basically it adds/removes/updates contacts from ContactList according
     * to what has happened to DF. It also fires events on the GUI any time a view refresh is
     * needed.
     *
     * @param inform the message from DF containing a list of changes
     */
    protected void handleInform(ACLMessage inform) {

      myLogger.log(
          Logger.FINE,
          "Thread " + Thread.currentThread().getId() + ": Notification received from DF");
      ContactManager.getInstance().resetModifications();

      try {

        DFAgentDescription[] results = DFService.decodeNotification(inform.getContent());

        if (results.length > 0) {

          for (int i = 0; i < results.length; ++i) {
            DFAgentDescription dfd = results[i];
            AID contactAID = dfd.getName();
            // Do something only if the notification deals with an agent different from the current
            // one
            if (!contactAID.equals(myAgent.getAID())) {

              myLogger.log(
                  Logger.INFO,
                  "Thread "
                      + Thread.currentThread().getId()
                      + ":df says that agent "
                      + myAgent.getAID().getLocalName()
                      + " updates or registers");
              Iterator serviceIter = dfd.getAllServices();

              // Registered or updated
              if (serviceIter.hasNext()) {
                ServiceDescription serviceDesc = (ServiceDescription) serviceIter.next();
                Iterator propertyIt = serviceDesc.getAllProperties();
                Location loc = Helper.extractLocation(propertyIt);
                String phoneNum = contactAID.getLocalName();
                ContactManager.getInstance().addOrUpdateOnlineContact(phoneNum, loc);
              } else {
                myLogger.log(
                    Logger.INFO,
                    "Thread "
                        + Thread.currentThread().getId()
                        + ":df says that agent "
                        + myAgent.getAID().getLocalName()
                        + " deregisters");
                String phoneNumber = contactAID.getLocalName();
                Contact c = ContactManager.getInstance().getContact(phoneNumber);
                ContactManager.getInstance().setContactOffline(phoneNumber);
                MsnEvent event =
                    MsnEventMgr.getInstance().createEvent(MsnEvent.CONTACT_DISCONNECT_EVENT);
                event.addParam(MsnEvent.CONTACT_DISCONNECT_PARAM_CONTACTNAME, c.getName());
                MsnEventMgr.getInstance().fireEvent(event);
              }

              MsnEvent event = MsnEventMgr.getInstance().createEvent(MsnEvent.VIEW_REFRESH_EVENT);
              ContactListChanges changes = ContactManager.getInstance().getModifications();
              Map<String, Contact> cMap = ContactManager.getInstance().getAllContacts();
              Map<String, ContactLocation> cLocMap =
                  ContactManager.getInstance().getAllContactLocations();

              myLogger.log(
                  Logger.FINE,
                  "Thread "
                      + Thread.currentThread().getId()
                      + ":Adding to VIEW_REFRESH_EVENT this list of changes: "
                      + changes.toString());
              event.addParam(MsnEvent.VIEW_REFRESH_PARAM_LISTOFCHANGES, changes);
              event.addParam(MsnEvent.VIEW_REFRESH_CONTACTSMAP, cMap);
              event.addParam(MsnEvent.VIEW_REFRESH_PARAM_LOCATIONMAP, cLocMap);
              MsnEventMgr.getInstance().fireEvent(event);
            }
          }
        }

      } catch (Exception e) {
        myLogger.log(Logger.WARNING, "See printstack for Exception.", e);
        e.printStackTrace();
      }
    }