Kernel SDK Developer's Guide > Dictionaries of Objects > Example of Working with a Dictionary
Example of Working with a Dictionary

A custom class will be an element of a dictionary and a testing program will modify the dictionary containing custom styles. A style will be defined by the width and height that specify a box and the justification of something in the box. The testing program must create the dictionary that stores these custom styles and must manipulate by the dictionary using the standard dictionary interface.

The example will first implement a class named xSomeStyle to provide the functionality of a style which must include creating a style, setting height and width, and getting height, width, and justification. The example will derive the xSomeStyle classes directly from the OdRxObject class. To declare the standard RTTI methods, the example will use the ODRX_DECLARE_MEMBERS macro. To implement the standard RTTI methods, the example will use the ODRX_CONS_DEFINE_MEMBERS macro.

Next the example will implement a console menu that will manipulate items of the dictionary and implement additional functions for printing results and entering data.

Step 1. Implementing the xSomeStyle auxiliary class

The xSomeStyle class defines the width and height as double values. To manipulate styles, this class declares the initStyle() method that specifies the width, height, and justification for a style, the getWidth() method that returns the current width value, the getHeight() method that returns the current height value, and the getJustify method that returns the current justification value. The xSomeStyle class has the following definition:

enum xJustification { xJustCenter, xJustLeftTop, xJustLeftBottom, xJustRightTop, xJustRightBottom };

class xSomeStyle : public OdRxObjectImpl<OdRxObject>
{
 private:
   double height;
   double width;
   xJustification justify;
 public:
   ODRX_DECLARE_MEMBERS(xSomeStyle);

   double getHeight() const;
   double getWidth() const;
   xJustification getJustify() const;
   void initStyle(double newHeight, double newWidth, xJustification newJustify);

   xSomeStyle();
   ~xSomeStyle();
};

typedef OdSmartPtr<xSomeStyle> xSomeStylePtr;

Its methods have the following implementation:

ODRX_CONS_DEFINE_MEMBERS(xSomeStyle, OdRxObject, NEWOBJ_CONSTR);

xSomeStyle::xSomeStyle() {  height = width = 0;   justify = xJustCenter;  }

xSomeStyle::~xSomeStyle() { }

double xSomeStyle::getHeight() const  {  return height;  }

double xSomeStyle::getWidth() const  {  return width;  }

xJustification xSomeStyle::getJustify() const  {  return justify;  }

void xSomeStyle::initStyle(double newHeight, double newWidth, xJustification newJustify)
{
   height = newHeight;
   width = newWidth;
   justify = newJustify;
}

Step 2. Implementing the testing functions

For working with a dictionary, the example uses a console menu that represents the following operations: creating an instance of the custom style and adding it in the dictionary with the specified keyword, removing an item from the dictionary and deleting the instance associated with it using the specified keyword or ID, getting a keyword for the specified ID, getting an ID for the specified keyword, getting an instance for the specified keyword or ID and printing information about the instance, and modifying a keyword for the specified ID and printing the items.

To print the information about a style object, the example implements the PrintStyleInstane() function that requires the smart pointer to the style instance as an argument and displays the address of the specified instance, width value using the GetWidth() method, height value using the GetHeight() method, and justification using the GetJustify() method.

To print the list of items, the example implements the PrintDictionaryItems() function which requires the smart pointer to the dictionary object and displays the ID, keyword, address, width, height, and justification for each style instance stored in the dictionary. To iterate through the dictionary, this function creates an iterator using the newIterator() method of the specified dictionary object and creates a loop using the done() and next() methods until the traversing is completed for the iterator. The PrintDictionaryItems() function gets the ID using the id() method, keyword using the getKey() method, smart pointer to the style instance using the object() method, and prints information about the style using PrintStyleInstance() function.

To enter a style, the example implements the AddStyleInstance() function which requires the smart pointer to the dictionary object where a new style instance must be added as a first argument and keyword of a new style instance as a second argument. The function inquires the width value and height value of a style, creates a new style instance using its createObject() method, initializes it using the initStyle() method, adds the style instance in the dictionary using the putAt() method of the dictionary, and returns the smart pointer to the created style instance.

To check whether a string contains only digits and can be considered as an ID, the example implements the IdFromString() function which requires the raw pointer to the string as an argument and checks each symbol. If the passed string consists only of digits, the IdFromString() function converts it to an integer value using the _wtoi() standard function and returns the converted value as an ID. If the passed string contains other characters besides digits, the IdFromString() function returns (–1). The (–1) result indicates the entered string as a keyword.

The main() function uses the odrxCreateRxDictionary() global function to create the dictionary object that is modified by the console menu. The main() function implements the console menu for the listed operations. It creates the loop that inquires about the operation to be performed and uses the switch operator to select whether the case must be performed. When the main() function performs the selected operation, it inquires about the string as a wide-character array and checks whether the entered string consists of digits using the IdFromString() function. If the entered string is an ID (result is not (–1)), the main() function uses the corresponding overloaded method of the dictionary object that requires an identification number and passes to it the ID as an argument. If the entered string is not an ID (result is (–1)), the main() function uses the corresponding overloaded method of the dictionary object which requires a keyword and passes to it the keyword as an argument. To check whether the entered keyword or ID exists in the dictionary, the main function uses the has() method before calling the method that performs the selected operation.

The main() function uses the keyAt() method to get the keyword for the specified item ID, the idAt() method to get the item ID for the specified keyword, the resetKey() method to modify the keyword for the specified ID, the getAt() method to get the style instance for the specified keyword or ID, the remove() method to remove an item from the dictionary for the specified keyword or ID, the PrintStyleInstance() function to print information about the returned style instance, the PrintDictionaryItems() function to print information about items and instances of the dictionary, and AddStyleInstance() function to create a new style instance and add it to the dictionary. When the style instance is removed from the dictionary, its reference counter becomes equal to zero and it automatically deletes this instance.

The Main module has the following implementation:

#include "OdaCommon.h"
#include "OdToolKit.h"
#include "..\..\Teigha.dwg\Extensions\ExServices\ExHostAppServices.h"
#include "..\..\Teigha.dwg\Extensions\ExServices\ExSystemServices.h"

class MyApp : public ExSystemServices 
{
 protected:
   ODRX_USING_HEAP_OPERATORS(ExSystemServices);
 public:
   MyApp() {};
};

#include <iostream>
using namespace std;

OdUInt32 IdFromString(const wchar_t *str)
{
   for(int i=0 ; str[i] != L'\0' ; i++)
     switch(str[i])
     {
       case L'0':
       case L'1':
       case L'2':
       case L'3':
       case L'4':
       case L'5':
       case L'6':
       case L'7':
       case L'8':
       case L'9':
            continue;
       default:
            return (-1);
     }
   return (OdUInt32) _wtoi(str);
}

void PrintStyleInstance(xSomeStylePtr pStyle)
{
   wcout << L"Instance = " << hex << pStyle.get() << dec
         << L", Height = " << pStyle->getHeight() << L", Width = " << pStyle->getWidth()
         << L", Justify = " << pStyle->getJustify();
}

void PrintDictionaryItems(OdRxDictionaryPtr pDict)
{
   OdRxDictionaryIteratorPtr it = pDict->newIterator(OdRx::kDictCollated);

   wcout << L"\nItems = " << pDict->numEntries();
   while(!it->done())
   {
      wcout << L"\nID = " << it->id() << L", Name = " << it->getKey() << L"  ";
      PrintStyleInstance(it->object());
      it->next();
   }
}

xSomeStylePtr AddStyleInstance(OdRxDictionaryPtr pDict, wchar_t *keyword)
{
   double height, width;
   xSomeStylePtr pStyle;

   wcout << L"Entry the height value:>";
   wcin >> height;
   wcin.sync();

   if(wcin.fail())
   {
      wcin.clear();
      wcout << L"Invalid height value.\n\n";
      return pStyle;
   }

   wcout << L"Entry the width value:>";
   wcin >> width;
   wcin.sync();

   if(wcin.fail())
   {
      wcin.clear();
      wcout << L"Invalid width value.\n\n";
      return pStyle;
   }

   pStyle = xSomeStyle::createObject();
   pStyle->initStyle(height, width, xJustCenter);

   pDict->putAt(keyword, pStyle);

   return pStyle;
}

int main()
{
   OdStaticRxObject<MyApp> svcs;

   odInitialize(&svcs);
   xSomeStyle::rxInit();

   OdUInt32 id;
   wchar_t ch, keyword[32];

   OdRxDictionaryPtr pDict = odrxCreateRxDictionary();

   do {
     wcout << L"\nP. Print the list of items";
     wcout << L"\nC. Create a new instance in the dictionary";
     wcout << L"\nR. Remove an instance from the dictionary";
     wcout << L"\nK. Display Keyword for ID or ID for Keyword";
     wcout << L"\nG. Get the instance for Keyword or ID";
     wcout << L"\nM. Modify the keyword for ID";
     wcout << L"\nQ. Quit";
     wcout << L"\nSelect operation:>";
     ch = wcin.get();

     switch(ch)
     {
       case L'P':
       case L'p':
         PrintDictionaryItems(pDict);
         wcout << L"\n\n";
         break;

       case L'C':
       case L'c':
         wcout << L"\nEntry a keyword for a new instance:>" ;
         wcin >> keyword;

         if(pDict->has(keyword) == true)
           wcout << L"\nKeyword = \"" << keyword << L"\" - already exists in the dictionary\n\n";
         else
           AddStyleInstance(pDict, keyword);
         break;

       case L'R':
       case L'r':
         wcout << L"\nEntry a keyword or ID to be deleted:>" ;
         wcin >> keyword;
         id = IdFromString(keyword);

         if(pDict->has(id) == true)
         {
           PrintStyleInstance(pDict->remove(id));
           wcout << L" - is deleted";
         }
         else if(pDict->has(keyword) == true)
         {
           PrintStyleInstance(pDict->remove(keyword)); 		
           wcout << L" - is deleted";
         }
         else
           wcout << L"\nKeyword or ID = \"" << keyword << L"\" - is not found\n\n";
         break;

       case L'K':
       case L'k':
         wcout << L"\nEntry a keyword to get ID or ID to get a keyword:>" ;
         wcin >> keyword;
         id = IdFromString(keyword);

         if(pDict->has(id) == true)
           wcout << L"\nID = " << id << L" has Keyword = " << pDict->keyAt(id) << L"\n\n";
         else if(pDict->has(keyword) == true)
           wcout << L"\nKeyword = " << keyword << L" has ID = " << pDict->idAt(keyword) << L"\n\n";
         else
           wcout << L"\nKeyword or ID = \"" << keyword << L"\" - is not found\n\n";
         break;

       case L'G':
       case L'g':
         wcout << L"\nEntry a keyword or ID to get an instance:>" ;
         wcin >> keyword;
         id = IdFromString(keyword);

         wcout << "\n";
         if(pDict->has(id) == true)
           PrintStyleInstance(pDict->getAt(id));
         else if(pDict->has(keyword) == true)
           PrintStyleInstance(pDict->getAt(keyword)); 		
         else
           wcout << L"Keyword or ID = \"" << keyword << L"\" - is not found";
         wcout << L"\n\n";
         break;

       case L'M':
       case L'm':
         wcout << L"\nEntry the item ID to be modify:>" ;
         wcin >> keyword;
         id = IdFromString(keyword);

         if(pDict->has(id) == true)
         {
           wcout << L"Entry a new keyword:>" ;
           wcin >> keyword;

           if(pDict->has(keyword) == true)
             wcout << L"\nKeyword = \"" << keyword << L"\" - already exists in the dictionary\n\n";
           else
             pDict->resetKey(id, keyword);
         }
         else
           wcout << L"\nThe ID = \"" << keyword << L"\" - is not found\n\n";
         break;
     }
     std::wcin.sync();
   }
   while(ch != L'Q' && ch != L'q');
	
   xSomeStyle::rxUninit();
   odUninitialize();

   return 0;
}

The testing actions give the following results:

P. Print the list of items
C. Create a new instance in the dictionary
R. Remove an instance from the dictionary
K. Display Keyword for ID or ID for Keyword
G. Get the instance for Keyword or ID
M. Modify the keyword for ID
Q. Quit
Select operation:>

When the operation is C-"Create a new instance in the dictionary":

Entry a keyword for a new instance:>AAA
Entry the height value:>1.2
Entry the width value:>2.3

Entry a keyword for a new instance:>BBB
Entry the height value:>4.5
Entry the width value:>5.6

Entry a keyword for a new instance:>CCC
Entry the height value:>7.8
Entry the width value:>8.9

When the operation is P-"Print the list of items":

Items = 3
ID = 0, Name = AAA  Instance = 0135A5D0, Height = 1.2, Width = 2.3, Justify = 0
ID = 1, Name = BBB  Instance = 0135A640, Height = 4.5, Width = 5.6, Justify = 0
ID = 2, Name = CCC  Instance = 0135A6B8, Height = 7.8, Width = 8.9, Justify = 0

When the operation is K-"Display Keyword for ID or ID for Keyword":

Entry a keyword to get ID or ID to get a keyword:>BBB
Keyword = BBB has ID = 1

Entry a keyword to get ID or ID to get a keyword:>2
ID = 2 has Keyword = CCC

Entry a keyword to get ID or ID to get a keyword:>23DE
Keyword or ID = "23DE" - is not found

When the operation is G-"Get the instance for Keyword or ID":

Entry a keyword or ID to get an instance:>1
Instance = 0135A640, Height = 4.5, Width = 5.6, Justify = 0

Entry a keyword or ID to get an instance:>CCC
Instance = 0135A6B8, Height = 7.8, Width = 8.9, Justify = 0

Entry a keyword or ID to get an instance:>23DE
Keyword or ID = "23DE" - is not found

When the operation is M-"Modify the keyword for ID":

Entry the item ID to be modify:>1
Entry a new keyword:>SSS

Entry the item ID to be modify:>2
Entry a new keyword:>DDD

Items = 3
ID = 0, Name = AAA  Instance = 0135A5D0, Height = 1.2, Width = 2.3, Justify = 0
ID = 1, Name = SSS  Instance = 0135A640, Height = 4.5, Width = 5.6, Justify = 0
ID = 2, Name = DDD  Instance = 0135A6B8, Height = 7.8, Width = 8.9, Justify = 0

When the operation is R-"Remove an instance from the dictionary":

Entry a keyword or ID to be deleted:>0
Instance = 0135A5D0, Height = 1.2, Width = 2.3, Justify = 0 - is deleted

Entry a keyword or ID to be deleted:>DDD
Instance = 0135A6B8, Height = 7.8, Width = 8.9, Justify = 0 - is deleted

Items = 1
ID = 1, Name = SSS  Instance = 0135A640, Height = 4.5, Width = 5.6, Justify = 0

Use the Q-"Quit" operation to exit.

See Also

Working with Dictionaries

Functionality of Dictionaries

Iterating through Items of a Dictionary

Copyright © 2002 – 2020. Open Design Alliance. All rights reserved.