/*
 * @copyright(disclaimer)                                                     *
 *                                                                            *
 * DISCLAIMER OF WARRANTIES.                                                  *
 *                                                                            *
 * The following IBM Content Manager Enterprise Edition code is sample code   *
 * created by IBM Corporation. IBM grants you a nonexclusive copyright        *
 * license to use this sample code example to generate similar function       *
 * tailored to your own specific needs. This sample code is not part of any   *
 * standard IBM product and is provided to you solely for the purpose of      *
 * assisting you in the development of your applications. This example has    *
 * not been thoroughly tested under all conditions. IBM, therefore cannot     *
 * guarantee nor may you imply reliability, serviceability, or function of    *
 * these programs. The code is provided "AS IS", without warranty of any      *
 * kind. IBM shall not be liable for any damages arising out of your or any   *
 * other parties use of the sample code, even if IBM has been advised of the  *
 * possibility of such damages. If you do not agree with these terms, do not  *
 * use the sample code.                                                       *
 *                                                                            *
 * Licensed Materials - Property of IBM                                       *
 * 5724-B19, 5697-H60                                                         *
 * � Copyright IBM Corp. 1994, 2013 All Rights Reserved.                      *
 *                                                                            *
 * US Government Users Restricted Rights - Use, duplication or disclosure     *
 * restricted by GSA ADP Schedule Contract with IBM Corp.                     *
 *                                                                            *
 * @endCopyright                                                              *
 */

// sample connect/execute/disconnect to V4
/*
 * Filename       : TEvaluateV4.cpp
 * Description    : Connect to V4 Datastore.
 *                  Create query string.
 *                  Specify to retrieve folder and documents.
 *                  Specify to retrieve a max result of 5 items.
 *                  Get the result in a resultset cursor.
 *                  Loop thru results.
 *                  Display documents found and their parts and attributes,
 *                   if folders found display them and their documents/
 *                   folders.
 *                  Disconnect from V4 Datastore.
 */

#ifdef MSVC71
  #include <iostream>
  using namespace std;
#else
  #include <iostream.h>
#endif

#include <stdio.h>                
#include <DKConstant.h>
#include <DKDatastoreV4.hpp>
#include <DKException.hpp>
#include <DKString.hpp>
#include <DKResults.hpp>
#include <DKStorageManageInfoV4.hpp>
#include <DKDDO.hpp>
#include <DKAny.hpp>
#include <DKPid.hpp>
#include <dkCollection.hpp>
#include <DKBlobV4.hpp>
#include <DKPidXDOV4.hpp>
#include <DKEnvironment.hpp>

void processResults(dkCollection* results);
void processFolder(dkCollection* results);
void processParts(dkCollection* results);
void processDDO(DKDDO *p);
void processXDO(dkXDO *pXDO);

void main(int argc, char *argv[])
{
    cout << "begin..." << endl;

    // Indicate this is a Console Application on Windows NT/95 for error
    // message code page conversion to OEM code page. If this was a Windows
    // GUI (Graphic User Interface) Application this would not be necessary
    // because DK_SS_WINDOWS is the default.
    DKEnvironment::setSubSystem(DK_SS_CONSOLE);

    //-------------------------------------------------------------- 
    // Checking for input parameters
    //--------------------------------------------------------------   
    if (argc < 4)
    {
     cout<<"Usage: "<<endl;
     cout<<"  TEvaluateV4 <libsrv> <userid> <pw>" << endl;
     return;
    }
    // ### get input parameters
    DKString libsrv = DKString(argv[1]);
    DKString userid = DKString(argv[2]);
    DKString pw = DKString(argv[3]);
    try {
    DKDatastoreV4 dsV4;
    DKAny aRes;
    DKResults* pCol = 0;
    cout << "Datastore V4 created" << endl;
    cout << "connecting to datastore" << endl;
    dsV4.connect(libsrv,userid,pw);
    cout << "datastore connected " << libsrv << " userid - " << userid << endl;
    DKString cmd = "SEARCH=(INDEX_CLASS=NOINDEX,";
    cmd += "MAX_RESULTS=5,";
    cmd += "COND=(Source <> NULL));";
    cmd += "OPTION=(CONTENT=YES;";
    cmd += "TYPE_QUERY=DYNAMIC;TYPE_FILTER=FOLDERDOC)";
    cout << "query string " << cmd << endl;
    cout << "executing query" << endl;
    aRes = dsV4.evaluate(cmd);
    pCol = (DKResults*)((dkCollection*)aRes);
    cout << "query executed" << endl;
    cout << "process results" << endl;
    processResults(pCol);
    cout << "results processed" << endl;
    dsV4.disconnect();
    cout << "datastore disconnected" << endl;
    }
    catch(DKException &exc)
    {

      cout << "Error id " << exc.errorId() << endl;
      cout << "Exception id " << exc.exceptionId() << endl;
      for(unsigned long i = 0; i< exc.textCount();i++)
      {
       cout << "Error text: " << exc.text(i) << endl;
      }
      for (unsigned long g=0; g< exc.locationCount();g++)
      {
       const DKExceptionLocation* p = exc.locationAtIndex(g);
       cout << "Filename: " << p->fileName() << endl;
       cout << "Function: " << p->functionName() << endl;
       cout << "LineNumber: " << p->lineNumber() << endl;
      }
      cout << "Exception Class Name: " << exc.name() << endl;
    }
    cout << "done ..." << endl;

}

void processDDO(DKDDO* p)
{
 DKPid *pid = 0;
 DKString strPid;
 DKAny a;
 ushort j = 0;
 ushort k = 0;
 ushort val = 0;
 ushort cnt = 1;
 DKString strData = "";
 DKString strDataName = "";
 long lVal = 0;
 short sVal = 0;
 double dVal = 0;
 DKDate dateVal;
 DKTime timeVal;
 DKTimestamp timestampVal;
 DKAny aProp;
 ushort usDataPropType = 0;
 dkCollection* pCol = 0;
 ushort numDataItems = 0;
 pid = (DKPid*)p->getPidObject();
 strPid = pid->pidString();
 cout << "pid string " << strPid << endl;
 k = p->propertyId(DK_CM_PROPERTY_ITEM_TYPE);
 if (k > 0)
 {
  a = p->getProperty(k);
  val = a;
  cout << "******************************" << endl;
  switch (val)
  {
   case DK_CM_DOCUMENT :
   {
    cout << "Item is document " << endl;
    break;
   }
   case DK_CM_FOLDER :
   {
    cout << "Item is folder " << endl;
    break;
   }
  }
  cout << "******************************" << endl;
 }
 k = p->propertyId(DK_CM_PROPERTY_CHECKOUT);
 if (k > 0)
 {
  a = p->getProperty(k);
  strData = a;
  cout << "checkout prop " << strData << endl;
 }
 numDataItems = p->dataCount();
 cout << "Number of Data Items " << numDataItems << endl;
 for (j = 1; j <= numDataItems; j++)
 {
  a = p->getData(j);
  strDataName = p->getDataName(j);
  aProp = p->getDataPropertyByName(j,DK_CM_PROPERTY_TYPE);
  usDataPropType = (ushort)aProp;
  switch (usDataPropType)
  {
   case DK_CM_DATAITEM_TYPE_STRING :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " String value :  null " << endl;
    }
    else
    {
     strData = a;
     cout << "attribute name : " << strDataName << " String value : " << strData << endl;
    }
    break;
   }
   case DK_CM_DATAITEM_TYPE_LONG :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " Long value :  null " << endl;
    }
    else
    {
     lVal = a;
     cout << "attribute name : " << strDataName << " Long value : " << lVal << endl;
    }
    break;
   }
   case DK_CM_DATAITEM_TYPE_SHORT :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " Short value :  null " << endl;
    }
    else
    {
     sVal = a;
     cout << "attribute name : " << strDataName << " Short value : " << sVal << endl;
    }
    break;
   }
   case DK_CM_DATAITEM_TYPE_DOUBLE :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " Double value :  null " << endl;
    }
    else
    {
     dVal = a;
     cout << "attribute name : " << strDataName << " Double value : " << dVal << endl;
    }
    break;
   }
   case DK_CM_DATAITEM_TYPE_DATE :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " Date value :  null " << endl;
    }
    else
    {
     dateVal = a;
     cout << "attribute name : " << strDataName << " Date value : " << dateVal << endl;
    }
    break;
   }
   case DK_CM_DATAITEM_TYPE_TIME :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " Time value :  null " << endl;
    }
    else
    {
     timeVal = a;
     cout << "attribute name : " << strDataName << " Time value : " << timeVal << endl;
    }
    break;
   }
   case DK_CM_DATAITEM_TYPE_TIMESTAMP :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " Timestamp value :  null " << endl;
    }
    else
    {
     timestampVal = a;
     cout << "attribute name : " << strDataName << " Timestamp value : " << timestampVal << endl;
    }
    break;
   }
   case DK_CM_DATAITEM_TYPE_COLLECTION_XDO :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " XDO Collection value :  null " << endl;
    }
    else
    {
     pCol = a;
     cout << "attribute name : " << strDataName << " XDO Collection value : " << pCol << endl;
     processParts(pCol);
    }
    break;
   }
   case DK_CM_DATAITEM_TYPE_COLLECTION_DDO :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " DDO Collection value :  null " << endl;
    }
    else
    {
     pCol = a;
     cout << "attribute name : " << strDataName << " DDO Collection value : " << pCol << endl;
     processFolder(pCol);
    }
    break;
   }
   default :
   {
    if (a.typeCode() == DKAny::tc_null)
    {
     cout << "attribute name : " << strDataName << " Unknown type value :  null " << endl;
    }
    else
    {
     cout << "attribute name : " << strDataName << " Unknown type value : " << a << endl;
    }
    break;
   }
  }
 }
}

void processXDO(dkXDO* pXDO)
{
 DKPidXDOV4 *pidXDO = 0;
 DKStorageManageInfoV4* pSmi = 0;
 DKBlobV4 *pBlob = (DKBlobV4*)pXDO;
 DKString strPid;
 pidXDO = (DKPidXDOV4*)pXDO->getPidObject();
 strPid = pidXDO->pidString();
 cout << "XDO pid string " << strPid << endl;
 pSmi = (DKStorageManageInfoV4*)pBlob->getExtension("DKStorageManageInfoV4");
 if (pSmi != 0)
 {
    long lRetention = pSmi->getRetention();
    DKString smsRetention(lRetention);
    DKString smsCollection   = pSmi->getCollectionName();
    DKString smsMgmtClass    = pSmi->getManagementClass();
    DKString smsStorageClass = pSmi->getStorageClass();
    DKString smsObjServer    = pSmi->getStoreSite();
    cout << "smsRetention=" << smsRetention << " smsCollection=" << smsCollection << " smsMgmtClass=" << smsMgmtClass << " smsStorageClass=" << smsStorageClass << " smsObjServer=" << smsObjServer << endl; 
 }
}

void processResults(dkCollection* results)
{
 dkIterator* iter = results->createIterator();
 DKDDO* item;
 DKAny *element;
 long i = 0;
 cout << "Begin Results **************** " << results << endl;
 cout << " number of items in DKResults " << results->cardinality() << endl;
 while(iter->more()) {
    element = iter->next();
    i++;
    item = (DKDDO*) element->value();
    if (!item) continue;
    cout << "*** DDO number " << i << " ***" << endl;
    //item->retrieve();
    processDDO(item);
 }
 delete iter;
 cout << "End Results **************** " << results << endl;
}

void processFolder(dkCollection* results)
{
 dkIterator* iter = results->createIterator();
 DKDDO* item;
 DKAny *element;
 long i = 0;
 cout << "Begin Folder **************** " << results << endl;
 cout << " number of items in DKFolder " << results->cardinality() << endl;
 while(iter->more()) {
    element = iter->next();
    i++;
    item = (DKDDO*) element->value();
    if (!item) continue;
    cout << "*** DDO number " << i << " ***" << endl;
    //  item->retrieve();
    processDDO(item);
 }
 delete iter;
 cout << "End Folder **************** " << results << endl;
}

void processParts(dkCollection* results)
{
 dkIterator* iter = results->createIterator();
 dkXDO* item;
 DKAny *element;
 long i = 0;
 cout << "Begin Parts **************** " << results << endl;
 cout << " number of items in DKParts " << results->cardinality() << endl;
 while(iter->more()) {
    element = iter->next();
    i++;
    item = (dkXDO*) element->value();
    if (!item) continue;
    cout << "*** XDO number " << i << " ***" << endl;
    //item->retrieve();
    processXDO(item);
 }
 delete iter;
 cout << "End Parts **************** " << results << endl;
}