Drawings SDK Developer Guide > Working with .dwg Files > Working with Databases > Identifying the Objects of Databases > Identification using an ID
Identification using an ID

An ID stores a unique identifier of an object within the scope across all databases loaded at run-time. An ID exists only during the current run-time session until the database is loaded into memory. The database associates an ID with an object and its handle. When a drawing is saved in a file, IDs are not saved. The database creates new IDs each time a drawing is loaded into memory. Programmatically, an ID is a specific structure named OdDbStub and contains a handle associated with an object, smart pointer to an object, pointer to a database, and pointer to an owner.

The OdDbObjectId class implements an ID and represents the interface for getting and modifying an identification value. The OdDbObjectId class does not inherit the standard database functionality; it is a specific structure for associating objects of a database. This class declares a pointer to the specific internal class, named OdDbStub, that contains four members: smart pointer that addresses the referenced object in memory, handle associated with the referenced object, pointer to the database that contains the referenced object, and pointer to an owner that possesses the referenced object.

In the examples below, the pHost variable stores a pointer to the host application object and the pDb variable stores a pointer to the database object.


OdDbDabasePtr pDb = pHost->createDatabase();                                          // Db = 3c9b8

Creating an ID

To create an ID, use its constructor. The OdDbObjectId class has a single constructor that creates an ID instance initialized by the kNull value. For example:


// create an ID
OdDbObjectId id;
odPrintConsoleString(L"\nHandle = %llx, Db = %lx", id.getHandle(), id.database());    // Handle = 0, Db = 0

Null ID

The OdDbObjectId class declares a special notation — OdDb::kNull — which defines a null value for an ID instance, denoting an undefined identifier that refers to nothing. An ID that equals kNull is not associated with an object and has a handle equal to zero.

To check whether an ID is null, use the isNull() method which does not have arguments and returns True when an ID is set to kNull or False when an ID is associated with an object. For example:


odPrintConsoleString(L"\nID %s", (id.isNull()) ? L"is kNull" : L"is associated");

To check an ID, you may also use the Not operator which calls the isNull() method and determines its returned value. For example:


if(!id)
  odPrintConsoleString(L"\nID is kNull");
else
  odPrintConsoleString(L"\nID is [%llx:%lx]", id.getHandle(), id.database());

To set an ID to kNull, use the setNull() method which does not have arguments, does not return a value, and sets the ID to kNull. For example:


id.setNull();
odPrintConsoleString(L"\nisNull() = %d", id.isNull());    // =1 - kNull,  =0 - not kNull

Getting a database, handle, and object from an ID

To get a database associated with an ID, use the database() method which does not have arguments and returns a pointer to the database object that contains the object associated with the ID, or NULL when the ID is not associated with an object or is set to kNull. For example:


OdDbDatabase* pIdDb = id.database();
if(pIdDb == NULL)
  odPrintConsoleString(L"\nID is not associated with a database");
else
  odPrintConsoleString(L"\nID is associated with database: %lx - %s", pIdDb, pIdDb->getFilename().c_str());

To get a handle associated with an ID and referenced object, use the getHandle() method which does not have arguments and returns the handle assigned to the object associated with the ID or zero when the ID is not associated with an object or is set to kNull. To check the returned handle, use its isNull() method. For example:


OdDbHandle handle = id.getHandle();
if(handle.isNull())
  odPrintConsoleString(L"\nID is not associated with a handle");
else
  odPrintConsoleString(L"\nID is associated with handle = %s", handle.ascii().c_str());

To get an object associated with an ID, use the safeOpenObject() method or openObject() method which requires the open mode as the first argument of the OdDb::OpenMode type, the erase status as the second argument of a Boolean type, and returns the smart pointer to the object opened in the specified mode. To check the result of the safeOpenObject() method, use the try...catch statement to process exceptions. For example:


OdDbObjectPtr pObject;
try {
  pObject = id.safeOpenObject(OdDb::kForWrite, false);

  odPrintConsoleString(L"\nObject=%lx, Handle=%llx, Type=%s", pObject, 
                       pObject->handle(), pObject->isA()->name().c_str());
}
catch(OdError& e) 
{ 
  odPrintConsoleString(L"\nObject is not opened, error: %d - %s", e.code(), e.description().c_str());
}

To check the result of the openObject() method, use the isNull() method of the returned smart pointer. This method does not generate an exception. For example:


OdDbObjectPtr pObj = id.openObject(OdDb::kForWrite, false);

if(pObj.isNull())
  odPrintConsoleString(L"\nObject=%lx, Handle=%llx, Type=%s", pObj, pObj->handle(), pObj->isA()->name().c_str());

Getting an ID

To get an ID, use the objectId() and ownerId() methods of the object, and the getOdDbObjectId() method, addOdDbObject() method, and specific methods of the database object. For details, see Getting an Identifier.

Redirecting an ID

When a database is embedded or is attached to another database, referencing an object requires redirecting. Redirecting defines the database that contains an object and how an ID must be converted to it. An ID can be redirected from other databases, for example when a database is attached through an external reference which can be inserted in a block of another database. The attached database is the original database, and handles of objects of the original database are the non-forwarded handles.

To convert a redirected ID into an actual ID, use the convertToRedirectedId() method which does not have arguments, does not return a value, and converts the ID to the ID of the original database. For example:


id.convertToRedirectedId();

To get the original database associated with a redirected ID, use the originalDatabase() method which does not have arguments and returns a pointer to the database object attached through an external reference. The original database contains the referenced object associated with the ID being used in the current workable database. When an ID is not redirected, the method returns the pointer to the current workable database. For example:


OdDbDatabase* pXRefDb = id.originalDatabase();
if(pXRefDb != NULL)
  odPrintConsoleString(L"\nID is associated with original database: %lx - %s", pXRefDb, pXRefDb->getFilename().c_str());

To get a handle of an object into its original database, use the getNonForwardedHandle() method which does not have arguments and returns the handle of the referenced object contained in the original database and associated with the ID. When an ID is not redirected, the method returns the handle of the current workable database. When an ID is set to kNull, the non-forwarded handle is set to zero. For example:


OdDbHandle handle = id.getNonForwardedHandle();
if(!handle.isNull())
  odPrintConsoleString(L"\nNon-forwarded handle = %s", handle.ascii().c_str());

Checking an ID

To check whether an object associated with an ID is erased, use the isErased() method which does not have arguments and returns True when an object is erased or False when an object exists. For example:


odPrintConsoleString(L"\nAssociated object %s", (id.isErased()) ? L"is erased" : L"exists");

To check whether an object associated with an ID is effectively erased, use the isEffectivelyErased() method; it does not have arguments and returns True when an object is erased or any of its ownership hierarchy is erased, or returns False otherwise. For example:


odPrintConsoleString(L"\nAssociated object %s", (id.isEffectivelyErased()) ? L"is erased" : L"exists");

To check whether an ID is valid, use the isValid() method which does not have arguments and returns True when an ID is valid or False when an ID is invalid. When an object is marked as "erased", it continues existing in the database, and its ID remains valid. When an object is permanently erased or an ID is kNull, the ID becomes invalid. For example:


odPrintConsoleString(L"\nID %s", (id.isValid()) ? L"is valid" : L"is invalid");

When an ID object is not associated with an object, the handle is set to zero, the pointer to the database is set to NULL, the pointer to the object is set to NULL, the erase status is True, and the ID is invalid and identified as kNull. When an ID object is associated with an object, the handle has an identifier, the pointer to a database is set to the address of an existing database, the pointer to an object is set to the address of an existing instance, the erase status is False, and the ID is valid. For example:


OdDbObjectId id1;
OdDbObjectId id2 = pDb1->getRegAppAcadId();

odPrintConsoleString(L"\nObj=%lx, Db=%lx, Handle=%llx, isNull=%d, isErased=%d, isValid=%d", id1.openObject(),  
                     id1.database(), id1.getHandle(), id1.isNull(), id1.isErased(), id1.isValid());
odPrintConsoleString(L"\nObj=%lx, Db=%lx, Handle=%llx, isNull=%d, isErased=%d, isValid=%d", id2.openObject(),
                     id2.database(), id2.getHandle(), id2.isNull(), id2.isErased(), id2.isValid());

// Result is following:
// Obj=0, Db=0, Handle=0, isNull=1, isErased=1, isValid=0
// Obj=4b0a2, Db=c9b08, Handle=12, isNull=0, isErased=0, isValid=1

Comparing an ID

To compare IDs, use the comparison operators that compare the ID objects taking into account the handle and database. For example:


OdDbDabasePtr pDb1 = pHost->createDatabase();
OdDbDabasePtr pDb2 = pHost->createDatabase();

OdDbObjectId id1 = pDb1->getLayerZeroId();
OdDbObjectId id2 = pDb2->getLayerZeroId();
OdDbObjectId id3 = pDb1->getLinetypeContinuousId();
OdDbObjectId id4 = pDb2->getLinetypeContinuousId();
OdDbObjectId id5 = ((OdDbSymbolTablePtr) pDb1->getLinetypeTableId().safeOpenObject())->getAt("Continuous");
OdDbObjectId id6 = ((OdDbSymbolTablePtr) pDb2->getLinetypeTableId().safeOpenObject())->getAt("Continuous");

odPrintConsoleString(L"\n1) %lx, %lx, %lx, %llx", id1.database(), id1.openObject(), id1.openObject()->isA(), id1.getHandle());
odPrintConsoleString(L"\n2) %lx, %lx, %lx, %llx", id2.database(), id2.openObject(), id2.openObject()->isA(), id2.getHandle());
odPrintConsoleString(L"\n3) %lx, %lx, %lx, %llx", id3.database(), id3.openObject(), id3.openObject()->isA(), id3.getHandle());
odPrintConsoleString(L"\n4) %lx, %lx, %lx, %llx", id4.database(), id4.openObject(), id4.openObject()->isA(), id4.getHandle());
odPrintConsoleString(L"\n5) %lx, %lx, %lx, %llx", id5.database(), id5.openObject(), id5.openObject()->isA(), id5.getHandle());
odPrintConsoleString(L"\n6) %lx, %lx, %lx, %llx", id6.database(), id6.openObject(), id6.openObject()->isA(), id6.getHandle());

// Compare the same object from different databases
odPrintConsoleString(L"\n(id1 == id2) = %d, (id1 != id2) = %d", (id1 == id2), (id1 != id2));
odPrintConsoleString(L"\n(id3 == id4) = %d, (id3 != id4) = %d", (id3 == id4), (id3 != id4));

// Compare the different objects from the same database
odPrintConsoleString(L"\n(id1 == id3) = %d, (id1 != id3) = %d", (id1 == id3), (id1 != id3));
odPrintConsoleString(L"\n(id2 == id4) = %d, (id2 != id4) = %d", (id2 == id4), (id2 != id4));

// Compare the different objects from different databases
odPrintConsoleString(L"\n(id1 == id4) = %d, (id1 != id4) = %d", (id1 == id4), (id1 != id4));
odPrintConsoleString(L"\n(id2 == id3) = %d, (id2 != id3) = %d", (id2 == id3), (id2 != id3));

// Compare the same object from the same database
odPrintConsoleString(L"\n(id3 == id5) = %d, (id3 != id5) = %d", (id3 == id5), (id3 != id5));
odPrintConsoleString(L"\n(id4 == id6) = %d, (id4 != id6) = %d", (id4 == id6), (id4 != id6));

// Result is following:
1) 13cb908, 13ccdf0, e9d130, 10
2) 13d3ab8, 13d51f0, e9d130, 10
3) 13cb908, 13cd518, e9d2f8, 16
4) 13d3ab8, 13d5968, e9d2f8, 16
5) 13cb908, 13cd518, e9d2f8, 16
6) 13d3ab8, 13d5968, e9d2f8, 16

(id1 == id2) = 0, (id1 != id2) = 1
(id3 == id4) = 0, (id3 != id4) = 1
(id1 == id3) = 0, (id1 != id3) = 1
(id2 == id4) = 0, (id2 != id4) = 1
(id1 == id4) = 0, (id1 != id4) = 1
(id2 == id3) = 0, (id2 != id3) = 1
(id3 == id5) = 1, (id3 != id5) = 0
(id4 == id6) = 1, (id4 != id6) = 0

Copying an ID

To copy an ID, use the Assignment operator that copies one ID to another ID. For example:


OdDbObjectId id1 = pDb1->getTextStyleStandardId();
OdDbObjectId id2 = id1;

odPrintConsoleString(L"\nH1=%llx, H2=%llx, (ID1==ID2)=%d", id1.getHandle(), id2.getHandle(), (id1 == id2));
// H1=12,  H2=12,  (ID1==ID2)=1

Associating an ID with an object

To associate an ID with an existing object of the loaded database, use the bindObject() method which requires a pointer to the object that is to be associated with the ID as an argument and performs binding of the ID and object. The bindObject() method initializes the ID instance. To bind correctly, the object must not be added in the database and the ID must not be kNull. For example:


OdDbColorPtr pColor = OdDbColor::createObject();
OdDbObjectId idColor = pDb->addOdDbObject(pColor);

OdDbColorPtr pNewColor = OdDbColor::createObject();

idColor.bindObject(pNewColor.get());

odPrintConsoleString(L"\nObj = %lx, Handle = %llx, Db = %lx", idColor.openObject(), idColor.getHandle(), idColor.database());

Note: The bindObject() method is implemented for internal use.

See Also

Identifying the Objects of Databases

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