Sample Code for the Synchronize Action

The following sample code demonstrates a complete synchronize action.

The synchronize action in this example generates documents for integers from 2 up to a configured limit IntegerLimit. Each document contains some properties of the integer as metadata.

The connector.hpp header file defines the MyConnector class, but does not provide the implementations of the functions. This example does not require the full <autonomy/connector/connector.hpp> include, and instead only includes the header <autonomy/connector/cppsdk/connectorBase.hpp>.

       // Source File: connector.hpp
       #include <autonomy/connector/cppsdk/connectorBase.hpp>
 
       namespace myconnectornamespace {
          using namespace autonomy::connector::cppsdk;

          class MyConnector : public ConnectorBase
          { 
          public:
             MyConnector();

             Features::feature_type features();

             void synchronize(const SynchronizeTask& task);
          };

       } //namespace myconnectornamespace

The implementation of the functions in the MyConnector class is in the connector.cpp source file. This file also includes the full <autonomy/connector/connector.hpp> and uses the CONNECTOR_LIBRARY_CLASS macro to specify the connector class to use.

The implementation of the synchronize function is directed to a new MySynchronize class.

       // Source File: connector.cpp
       #include "connector.hpp"
       #include "synchronize.hpp"

       #include <autonomy/connector/connector.hpp>

       namespace myconnectornamespace {
          using namespace autonomy::connector::cppsdk;

          MyConnector::MyConnector()
             : ConnectorBase("My Connector")
          {}

          Features::feature_type MyConnector::features()
          {
             return Features::synchronize;
          }

          void MyConnector::synchronize(const SynchronizeTask& task)
          {
             MySynchronize mySynchronize(task);
             mySynchronize.synchronize();
          }

       } //namespace myconnectornamespace

       CONNECTOR_LIBRARY_CLASS(myconnectornamespace::MyConnector)

The synchronize.hpp header file defines the MySynchronize class. This class performs the synchronization. Only the header <autonomy/connector/cppsdk/tasks/synchronizeTask.hpp> is included, and this includes all the classes that might be required for a synchronize action.

An instance of this class holds the SynchronizeTask object m_task and, for convenience, an instance of the DocInfoBuilder m_builder along with some additional data used during a call to the action.

The synchronize() function is called to begin the synchronization.

       // Source File: synchronize.hpp
       #include <autonomy/connector/cppsdk/tasks/synchronizeTask.hpp>

       namespace myconnectornamespace {

          using namespace autonomy::connector::cppsdk;
          class MySynchronize
          {
SynchronizeTask m_task; DocInfoBuilder m_builder; int m_limit; std::vector<int> m_largestFactor; public: MySynchronize(const SynchronizeTask& task); void synchronize(); DocInfo buildDocInfo(int n); }; } //namespace myconnectornamespace

The final source file synchronize.cpp contains the implementation of the action.

The implementation of parts of the functions is omitted here but can be found in full in the code samples provided in the SDK.

This code shows use of an IngestResultHandler to perform logging. It demonstrates the use of the shouldStop() function that is present to check whether the user has requested the action or the connector to stop. It also shows various ways to add data to a document.

       // Source File: synchronize.cpp
       #include "synchronize.hpp"

       #include <map>
       #include <set>

       namespace myconnectornamespace {

          using namespace autonomy::connector::cppsdk;

          class IngestResultHandler : public Ingester::ResultHandler
          {
             Log m_log;

             public:
                IngestResultHandler(const Log& log)
                : m_log(log)
             {}

             void operator()(const IngestTask& ingestTask)
             {
                if (ingestTask.status() == IngestTaskStatus::Done)
                {
                   m_log.full("Document " + ingestTask.document().reference()
                      + ", ingest " + ingestTask.typeString() + " succeeded!");
                }
                else
                {
                   m_log.full("Ingestion failed for " + ingestTask.document().reference());
                }
             }
          };

          // static std::string intToStr(int value) ...
 
          MySynchronize::MySynchronize(const SynchronizeTask& task)
             : m_task(task),
             m_builder(task.docInfoBuilder()),
             m_limit(task.taskConfig().getInt("IntegerLimit", 1000)),
             m_largestFactor(m_limit + 1, 0)
          {
             IngestResultHandler resultHandler(task.log());
             task.ingester().addResultHandler(resultHandler);

             // Perform some initialization ...
          }

          void MySynchronize::synchronize()
          {
             for (int n = 2; n <= m_limit; ++n)
             {
                if (m_task.shouldStop())
                   break;
   
                DocInfo docInfo = buildDocInfo(n);
                m_task.ingester().add(docInfo);
             }  
          }

          DocInfo MySynchronize::buildDocInfo(int n)
          {
             DocInfo docInfo = m_builder.createDocInfo(intToStr(n));
             Metadata metadata = docInfo.doc().metadata();

             metadata.addField("IS_PRIME", m_largestFactor[n] == n ? "TRUE" : "FALSE");
             Field factorsField = metadata.addField("FACTORS");

             // Local variables ...
   
             for (std::map<int, int>::const_iterator it = primeFactors.begin();
                it != primeFactors.end();
                ++it)
             {
                // Various calculations ...

                Field factorField = factorsField.addField("FACTOR");
                factorField.setAttribute("PRIME", intToStr(p));
                factorField.setAttribute("EXPONENT", intToStr(e));
             }

             // Construct additional field values ...

             docInfo.doc().appendContent(divs.str());
             return docInfo;
          }

       } //namespace myconnectornamespace
 

An example document produced by this code is shown below. To see the documents that are produced in the connector's temporary directory, set the parameter IngestWriteXML=TRUE in the [Ingestion] section of the configuration file.

<DOCUMENT>
  <DREREFERENCE>840</DREREFERENCE>
  <AUTN_GROUP>Connector</AUTN_GROUP>
  <AUTN_IDENTIFIER>PGlkIHM9Ik1ZVEFTSzEiIHI9Ijg0MCIvPg==</AUTN_IDENTIFIER>
  <DIVISORS>32</DIVISORS>
  <DocTrackingId>fa83a11a198d5a7f0bf77a1987bcd006</DocTrackingId>
  <FACTORIZATION>2^3 3^1 5^1 7^1</FACTORIZATION>
  <FACTORS>
    <FACTOR PRIME="2" EXPONENT="3"/>
    <FACTOR PRIME="3" EXPONENT="1"/>
    <FACTOR PRIME="5" EXPONENT="1"/>
    <FACTOR PRIME="7" EXPONENT="1"/>
  </FACTORS>
  <IS_PRIME>FALSE</IS_PRIME>
  <IS_SQUAREFREE>FALSE</IS_SQUAREFREE>
  <TOTIENT>192</TOTIENT>
  <DRECONTENT>1 2 3 4 5 6 7 8 10 12 14 15 20 21 24 28 30 35 40 42 56 60 70 84 105 120 140 168 210 280 420 840</DRECONTENT>
</DOCUMENT>