// Generate the default content for presence status.
void PresenceDefaultConstructor::generateDefaultContent(SipPublishContentMgr* contentMgr,
							const char* resourceId,
							const char* eventTypeKey,
							const char* eventType)
{
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "PresenceDefaultConstructor::generateDefaultContent "
                 "generating default content for resourceId '%s', "
                 "eventTypeKey '%s', eventType '%s'",
                 resourceId, eventTypeKey, eventType);

   // Create a presence event package and store it in the publisher.
   // This code parallels SipPresenceMonitor::setStatus.
   SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(resourceId);

   UtlString id;
   UtlString resource(resourceId);
   SipPresenceMonitor::makeId(id, resource);
   Tuple* tuple = new Tuple(id.data());
   tuple->setStatus(DEFAULT_PRESENCE_STATUS);
   tuple->setContact(resourceId, 1.0);

   sipPresenceEvent->insertTuple(tuple);

   // Build its text version.
   sipPresenceEvent->buildBody();

   // Publish the event (storing it for the resource), but set
   // noNotify to TRUE, because our caller will push the NOTIFYs.
   contentMgr->publish(resourceId, eventTypeKey, eventType, 1,
                       &(HttpBody*&) sipPresenceEvent, TRUE);
}
bool SipPresenceMonitor::setStatus(const Url& aor, const Status value)
{
   bool result = false;
   
   UtlString contact;
   aor.getIdentity(contact);
   
   // Create a presence event package and store it in the publisher
   SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(contact);
      
   UtlString id;
   NetMd5Codec::encode(contact, id);
   
   Tuple* tuple = new Tuple(id.data());
   
   if (value == StateChangeNotifier::PRESENT)
   {
      tuple->setStatus(STATUS_OPEN);
      tuple->setContact(contact, 1.0);
   }
   else
   {
      if (value == StateChangeNotifier::AWAY)
      {
         tuple->setStatus(STATUS_CLOSE);
         tuple->setContact(contact, 1.0);
      }
   }

   sipPresenceEvent->insertTuple(tuple); 
   
   // Add the SipPresenceEvent object to the subscribe list
   result = addPresenceEvent(contact, sipPresenceEvent);
   
   return result;
} 
// Returns TRUE if the requested state is different from the current state.
bool SipPresenceMonitor::setStatus(const Url& aor, const Status value)
{
   if (OsSysLog::willLog(FAC_SIP, PRI_DEBUG))
   {
      UtlString aorString;
      aor.toString(aorString);
      OsSysLog::add(FAC_SIP, PRI_DEBUG,
                    "SipPresenceMonitor::setStatus aor = '%s', value = %d %s",
                    aorString.data(), value,
                    (value == StateChangeNotifier::PRESENT ? "PRESENT" :
                     value == StateChangeNotifier::AWAY ? "AWAY" :
                     "UNKNOWN"));
   }

   bool result = false;

   UtlString contact;
   aor.getUserId(contact);
   contact += mHostAndPort;
   // Make the contact be a proper URI by prepending "sip:".
   contact.prepend("sip:");

   // Create a presence event package and store it in the publisher
   SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(contact);

   UtlString id;
   makeId(id, contact);

   Tuple* tuple = new Tuple(id.data());

   tuple->setStatus(value == StateChangeNotifier::PRESENT ?
                    STATUS_OPEN :
                    STATUS_CLOSED);
   tuple->setContact(contact, 1.0);

   sipPresenceEvent->insertTuple(tuple);

   // Add the SipPresenceEvent object to the presence event list.
   result = addPresenceEvent(contact, sipPresenceEvent);

   return result;
}
   void testGetPresencePackage()
      {
         const char *package = 
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" entity=\"[email protected]\">\n"
            "<tuple id=\"1\">\n"
            "<status>\n"
            "<basic>open</basic>\n"
            "</status>\n"
            "<contact>tel:+0123456789</contact>\n"
            "</tuple>\n"
            "</presence>\n"
            ;
       
         SipPresenceEvent presenceEvent("*****@*****.**");
         
         UtlString id = "1";
         Tuple* tuple = new Tuple(id);

         tuple->setStatus("open");
         tuple->setContact("tel:+0123456789", 1.0);

         presenceEvent.insertTuple(tuple);

         UtlString bodyString;
         int bodyLength;
       
         presenceEvent.getBytes(&bodyString, &bodyLength);
         //printf("body = \n%s\n", bodyString.data());

         CPPUNIT_ASSERT(strcmp(bodyString.data(), package) == 0);

         int otherLength = presenceEvent.getLength();
         CPPUNIT_ASSERT_EQUAL_MESSAGE("content length is not equal",
                                      bodyLength, otherLength);
      }
// Read the presence events from the persistent file.
void SipPresenceMonitor::readPersistentFile()
{
   mLock.acquire();

   // Initialize Tiny XML document object.
   TiXmlDocument document;
   TiXmlNode* items_node;
   if (
      // Load the XML into it.
      document.LoadFile(mPersistentFile.data()) &&
      // Find the top element, which should be an <items>.
      (items_node = document.FirstChild("items")) != NULL &&
      items_node->Type() == TiXmlNode::ELEMENT)
   {
      // Find all the <item> elements.
      int item_seq_no = 0;
      for (TiXmlNode* item_node = 0;
           (item_node = items_node->IterateChildren("item",
                                                    item_node));
         )
      {
         if (item_node->Type() == TiXmlNode::ELEMENT)
         {
            item_seq_no++;
            TiXmlElement* item_element = item_node->ToElement();

            // Process the <item> element.
            bool item_valid = true;

            // Process the 'id' child.
            UtlString id;
            TiXmlNode* id_node = item_element->FirstChild("id");
            if (id_node && id_node->Type() == TiXmlNode::ELEMENT)
            {
               textContentShallow(id, id_node);
               if (id.isNull())
               {
                  // Id null.
                  OsSysLog::add(FAC_ACD, PRI_ERR,
                                "id child of <item> was null");
                  item_valid = false;
               }
            }
            else
            {
               // Id missing.
               OsSysLog::add(FAC_ACD, PRI_ERR,
                             "id child of <item> was missing");
               item_valid = false;
            }

            // Process the 'contact' child.
            UtlString contact;
            TiXmlNode* contact_node = item_element->FirstChild("contact");
            if (contact_node && contact_node->Type() == TiXmlNode::ELEMENT)
            {
               textContentShallow(contact, contact_node);
               if (contact.isNull())
               {
                  // Contact null.
                  OsSysLog::add(FAC_ACD, PRI_ERR,
                                "contact child of <item> was null");
                  item_valid = false;
               }
            }
            else
            {
               // Contact missing.
               OsSysLog::add(FAC_ACD, PRI_ERR,
                             "contact child of <item> was missing");
               item_valid = false;
            }

            // Process the 'status' child.
            UtlString status;
            TiXmlNode* status_node = item_element->FirstChild("status");
            if (status_node && status_node->Type() == TiXmlNode::ELEMENT)
            {
               textContentShallow(status, status_node);
               if (status.isNull())
               {
                  // Status null.
                  OsSysLog::add(FAC_ACD, PRI_ERR,
                                "status child of <item> was null");
                  item_valid = false;
               }
            }
            else
            {
               // Status missing.
               OsSysLog::add(FAC_ACD, PRI_ERR,
                             "status child of <item> was missing");
               item_valid = false;
            }

            OsSysLog::add(FAC_ACD, PRI_DEBUG,
                          "SipPresenceMonitor::readPersistentFile row: id = '%s', contact = '%s', status = '%s'",
                          id.data(), contact.data(), status.data());

            if (item_valid)
            {
               // Create a presence event package and store it in
               // mPresenceEventList.
               SipPresenceEvent* sipPresenceEvent = new SipPresenceEvent(contact);
               Tuple* tuple = new Tuple(id.data());
               tuple->setStatus(status);
               tuple->setContact(contact, 1.0);
               sipPresenceEvent->insertTuple(tuple);
               sipPresenceEvent->buildBody();
               mPresenceEventList.insertKeyAndValue(new UtlString(contact),
                                                    sipPresenceEvent);
            }
            else
            {
            OsSysLog::add(FAC_ACD, PRI_ERR,
                          "In presence status file '%s', <item> number %d had invalid or incomplete information.  The readable information was: id = '%s', contact = '%s', status = '%s'",
                          mPersistentFile.data(), item_seq_no,
                          id.data(), contact.data(), status.data());

            }
         }
      }
   }
   else
   {
      // Report error parsing file.
      OsSysLog::add(FAC_ACD, PRI_CRIT,
                    "Presence status file '%s' could not be parsed.",
                    mPersistentFile.data());
   }

   mLock.release();

   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "SipPresenceMonitorPersistenceTask::readPersistentFile done");
}