The wblockClone() method of an object cannot be overridden
itself. The method subWblockClone() contains all overridable
functionality and should be overridden in order to customize the wblock clone
behavior of an object.
To customize the copying stage of the wblock cloning operation:
Create an object of the same type as the current object, and add it to
the database.
Create a wblock clone filer and file out to it the current object using its
dwgOut() method.
Rewind the filer and read data to the clone using its
dwgIn() method.
Append a new record filled in with the information about the current
operation to the ID map.
Set the flag signaling that the clone's references have not been
translated yet and so they cannot be used in any operations with this
object. Call the clone's setOdDbObjectIdsInFlux() method for
this purpose.
Clone all objects referenced by the current object with hard ownership or
hard pointer references. This can be done by calling the
defaultProcessReferences() method of the wblock clone filer.
It will follow through all hard ownership and hard pointer references of
the object and call the wblockClone() method of referenced
objects.
Return the cloned object.
OdDbObjectPtr ExDcEntity::subWblockClone(OdDbIdMapping& idMap, OdDbObject* /*owner*/, bool bPrimary) const
{
// do not use the owner - override appendToOwner() virtual function
// if you need some special ownership processing
// You should always return NULL if, for any reason,
// you do not actually clone this object during this call.
//
OdDbObjectPtr pClone;
// Verify database pointer
//
if (!idMap.destDb())
{
throw OdError(eNoDatabase);
}
// If this is an xref bind operation and this entity is in paper space, then return,
// as xref bind doesn't support cloning entities in paper space.
//
OdDbDatabase* pDb = database();
if (idMap.deepCloneContext() == OdDb::kDcXrefBind && ownerId() == pDb->getPaperSpaceId())
{
return OdDbObjectPtr();
}
// If this object is in the idMap and is already cloned, then return.
//
OdDbIdPair idPair(objectId());
if (idMap.compute(idPair) && (idPair.isCloned() || !idPair.value().isNull()))
{
return OdDbObjectPtr();
}
// Step 1
// Create the clone and add it to the database.
//
pClone = isA()->create();
idMap.destDb()->addOdDbObject(pClone);
// Step 2
// The OdDbWblockCloneFiler makes a list of HardOwnership and HardPointer IDs.
// These references must be cloned during a wblock operation.
//
OdDbWblockCloneFilerPtr pFiler = OdDbWblockCloneFiler::createObject(&idMap);
dwgOut(pFiler);
// Step 3
// Rewind the filer and read the data into the clone.
//
pFiler->seek(0L, OdDb::kSeekFromStart);
pClone->dwgIn(pFiler);
// Step 4
// Add the new information to the ID map.
idPair.setValue(pClone->objectId());
idPair.setCloned(true);
idPair.setPrimary(bPrimary);
idMap.assign(idPair);
// Step 5
// Set flag that the cloned object's IDs have not yet been translated
// and thus cannot be used in any operations on the object.
// The flag is turned off after the object has translated
// the references to their new values.
//
pClone->setOdDbObjectIdsInFlux();
// Step 6
// Using the filer list created above, clone any hard references.
//
pFiler->defaultProcessReferences();
// Where default processing iterates through hard references
// and call wblockClone() method. Actually it does the following:
//
//OdDbObjectId hardId;
//pFiler->start();
//while (pFiler->nextReference(hardId))
//{
// hardId.safeOpenObject()->wblockClone(idMap);
//}
// Step 7
// Return the cloned object.
//
return pClone;
}