/*
 *  Copyright 1995,1996,1997 The Association for Information and Image Management Int'l
 *                                             1100 Wayne Avenue
 *                                             Silver Spring, MD 20910-5603
 *                                             Tel: 301/587-8202
 *                                             Fax: 301/587-2711
 *      All Rights Reserved.
 *      DMA (Document Management Alliance) working group.
 *
 *  
 * Code example: Pretty printing of a DMA object's properties. 
 *
 */

#include <stdio.h>

#include <dmatypes.h>
#include <dmacom.h>
#include <dmastr.h>
#include <dmarc.h>
#include <dmaiface.h>
#include <dmaenums.h>
#include <dmaids.h>
#include <dmaidvar.h>

/* Global reference to in effect IMalloc */
extern IMalloc *g_pMalloc;

char * g_rgpszTypes[] =
{
    "Illegal(0)",
    "Binary",
    "Boolean",
    "DateTime",
    "Float64",
    "Id",
    "Integer32",
    "Object"    
    "String",
};

void PrintDmaId (
    DmaId *pId )
{
    printf ( "%8.8lx-%4.4lx-%4.4lx-", pId->Data1, pId->Data2, pId->Data3 );
    printf ( "%2.2x%2.2x-", pId->Data4[0], pId->Data4[1] );
    for ( int I = 2; I < 8 ; I++ )
    {
        printf("%2.2x", pId->Data4[I] );
    }
}    

void GetAndPrintPropByIndex (
    IdmaProperties *pprop,
    DmaIndex32 iProp,
    DmaInteger32 lDatatype )
{
    DmaRC rc;

    switch ( lDatatype )
    {
    case DMA_DATATYPE_BOOLEAN:
        {
            DmaBoolean bValue;
            rc = pprop->GetPropValBooleanByIndex ( iProp, &bValue );
            if ( rc == DMARC_OK )
            {
                printf ( "%s\n", bValue ? "TRUE" : "FALSE" );
            }
        }
        break;

    case DMA_DATATYPE_INTEGER32:
        {
            DmaInteger32 lValue;
            rc = pprop->GetPropValInteger32ByIndex ( iProp, &lValue );
            if ( rc == DMARC_OK )
            {
                printf ( "%d\n", lValue );
            }
        }
        break;

    case DMA_DATATYPE_FLOAT64:
        {
            DmaFloat64 fValue;
            rc = pprop->GetPropValFloat64ByIndex ( iProp, &fValue );
            if ( rc == DMARC_OK )
            {
                printf ( "%f\n", fValue );
            }
        }
        break;

    case DMA_DATATYPE_STRING:
        {
            pDmaString pValue;
            rc = pprop->GetPropValStringByIndex ( iProp, &pValue );
            if ( rc == DMARC_OK )
            {
                printf ( "%ws\n", DMA_GET_STRING_TEXT(pValue) );
                DMA_FREE_STRING ( g_pMalloc->Free, pValue );
            }
        }
        break;

    case DMA_DATATYPE_DATETIME:
        {
            pDmaString pValue;
            rc = pprop->GetPropValDateTimeByIndex ( iProp, &pValue );
            if ( rc == DMARC_OK )
            {
                printf ( "%ws\n", DMA_GET_STRING_TEXT(pValue) );
                DMA_FREE_STRING ( g_pMalloc->Free, pValue );
            }
        }
        break;

    case DMA_DATATYPE_ID:
        {
            DmaId idValue;
            rc = pprop->GetPropValIdByIndex ( iProp, &idValue );
            if ( rc == DMARC_OK )
            {
                PrintDmaId ( &idValue );
                printf ( "\n" );
            }
        }
        break;

    case DMA_DATATYPE_OBJECT:
        {
            IdmaProperties *ppropSub;
            rc = pprop->GetPropValObjectByIndex ( iProp, IID_IdmaProperties,
                                                  (pDmapv)&ppropSub );
            if ( rc == DMARC_OK )
            {
                printf ( "OBJECT\n" );

                ppropSub->Release();
            }
        }
        break;

    case DMA_DATATYPE_BINARY:
        {
            DmaBinaryValue dbvValue;
            rc = pprop->GetPropValBinaryByIndex ( iProp, &dbvValue );
            if ( rc == DMARC_OK )
            {
                DmaUInteger32 ulLineCount = 0;
                for ( DmaUInteger32 iByte = 0; iByte < dbvValue.cbBytes ; iByte++ )
                {
                    printf ( "%2.2x", dbvValue.pbBytes[iByte] );
                    if ( ulLineCount == 7 )
                        printf ( "-" );
                    else if ( ulLineCount == 15 )
                        printf ( "\n" );
                    else
                        printf ( " " );

                    ulLineCount = (ulLineCount + 1) % 16;
                }

                g_pMalloc->Free ( dbvValue.pbBytes );
            }
        }
        break;

    default:
        printf ( "UNKNOWN DATATYPE %d\n", lDatatype );
        rc = DMARC_OK;
        break;
    }

    if ( rc == DMARC_VALUE_NOT_SET )
    {
        printf ( "VALUE NOT SET\n" );
    }
    else if ( rc != DMARC_OK )
    {
        printf ( "ERROR[%lx]\n", rc);
    }

}

void PrettyPrint (
    IdmaProperties *pObj )
{
    DmaRC rc;
    
    IdmaProperties *ppropCD;

    // First, get the class descriptor for the object
    rc = pObj->GetPropValObjectById ( &dmaProp_ClassDescription,
                                      IID_IdmaProperties,
                                      (pDmapv) &ppropCD );
    if ( rc == DMARC_OK )
    {
        // Further error handling omitted

        IdmaListOfObject *pPropList;
        rc = ppropCD->GetPropValObjectById ( &dmaProp_PropertyDescriptions,
                                             IID_IdmaListOfObject,
                                             (pDmapv) &pPropList );
        DmaInteger32 cProps;
        rc = pPropList->GetElementCount ( &cProps );

        for ( int iProp = 0; iProp < cProps ; iProp++ )
        {
            DmaRC rc;

            IdmaProperties *ppropPD;

            printf("%d: ", iProp );

            rc = pPropList->GetObject ( iProp, IID_IdmaProperties,
                                               (pDmapv)&ppropPD );

            pDmaString pName;

            rc = ppropPD->GetPropValStringById ( &dmaProp_DisplayName, 
                                                 &pName );
            printf ( "%ws: ", DMA_GET_STRING_TEXT(pName) );
            DMA_FREE_STRING ( g_pMalloc->Free, pName );

            DmaInteger32 lDatatype;
            rc = ppropPD->GetPropValInteger32ById ( &dmaProp_DataType,
                                                    &lDatatype );
            DmaInteger32 lCardinality;
            rc = ppropPD->GetPropValInteger32ById ( &dmaProp_Cardinality,
                                                    &lCardinality );
            if ( lCardinality == DMA_CARDINALITY_SINGLE )
            {
                GetAndPrintPropByIndex ( pObj, iProp, lDatatype );
            }
            else if ( lCardinality == DMA_CARDINALITY_LIST )
            {
                printf ( "LIST of %s: ", g_rgpszTypes[lDatatype] );
            }
            else
            {
                printf ( "ENUM of %s\n", g_rgpszTypes[lDatatype] );
            }

            ppropPD->Release();
        }

        pPropList->Release();
        ppropCD->Release();
    }
    else
    {
        printf ( "Error %lx retrieving class description\n", rc );
    }
}